Merge branch 'master' into tagging

* master: (30 commits)
  Fixing search positioning on saved stories.
  Fixing positioning of popover options in All Site Stories.
  Adding Split tooltip.
  Removing extra logging.
  Switching feedbar and navbar.
  Fixing mark folder as read.
  Removing double.
  Fixing mark as read on socialsubs.
  Adjusting positioning on new feedbar. Also scrolling to selected feed/folder when switch story layouts.
  Reloading feed list when adding, moving, and deleting feeds and folders.
  Reloading feeds on feed/folder add and feedchooser.
  Backend for marking feeds/folders as read at a specific timestamp.
  Adding expanded mark read buttons. Needs backend support.
  iOS v3. Fixed move site view folder placement as well.
  Moving feedbar down to bottom of screen. Prep for new mark read buttons.
  Fixing 2 ios crashes: double-tapping instapaper button and a weird keyboard condition.
  Fixing activities height for subscriptions on ios. Also turning river back on for third-party clients. That wasn't fair and it's hard to get users to upgrade. I'd rather give users the ability to use the product instead of crippling it, unless there is a proper workflow for upgrading, which only exists on the web today.
  Removing last traces of Google Reader from ios app. Also add better final page of ftux. Fixing folder chooser in add dialog on ios.
  Fixing colors on share/train buttons when active. Fixing height on profile cells.
  Stopping animation of share view/keyboard before orientation has changed.
  ...

Conflicts:
	media/js/newsblur/views/story_titles_header_view.js
This commit is contained in:
Samuel Clay 2013-09-14 11:55:48 -07:00
commit 84f79e5a81
65 changed files with 3312 additions and 2008 deletions

View file

@ -404,31 +404,37 @@ class UserSubscription(models.Model):
r.srem(read_stories_key, *stale_story_hashes)
r.srem("RS:%s" % self.feed_id, *stale_story_hashes)
def mark_feed_read(self):
def mark_feed_read(self, cutoff_date=None):
if (self.unread_count_negative == 0
and self.unread_count_neutral == 0
and self.unread_count_positive == 0
and not self.needs_unread_recalc):
return
now = datetime.datetime.utcnow()
recount = True
# Use the latest story to get last read time.
latest_story = MStory.objects(story_feed_id=self.feed.pk).order_by('-story_date').only('story_date').limit(1)
if latest_story and len(latest_story) >= 1:
latest_story_date = latest_story[0]['story_date']\
+ datetime.timedelta(seconds=1)
if cutoff_date:
cutoff_date = cutoff_date + datetime.timedelta(seconds=1)
else:
latest_story_date = now
latest_story = MStory.objects(story_feed_id=self.feed.pk).order_by('-story_date').only('story_date').limit(1)
if latest_story and len(latest_story) >= 1:
cutoff_date = (latest_story[0]['story_date']
+ datetime.timedelta(seconds=1))
else:
cutoff_date = datetime.datetime.utcnow()
recount = False
self.last_read_date = latest_story_date
self.mark_read_date = latest_story_date
self.unread_count_negative = 0
self.unread_count_positive = 0
self.unread_count_neutral = 0
self.unread_count_updated = now
self.oldest_unread_story_date = now
self.needs_unread_recalc = False
self.last_read_date = cutoff_date
self.mark_read_date = cutoff_date
self.oldest_unread_story_date = cutoff_date
if not recount:
self.unread_count_negative = 0
self.unread_count_positive = 0
self.unread_count_neutral = 0
self.unread_count_updated = datetime.datetime.utcnow()
self.needs_unread_recalc = False
else:
self.needs_unread_recalc = True
self.save()

View file

@ -856,6 +856,7 @@ def load_river_stories__redis(request):
query = request.REQUEST.get('query')
now = localtime_for_timezone(datetime.datetime.now(), user.profile.timezone)
usersubs = []
code = 1
offset = (page-1) * limit
limit = page * limit - 1
story_date_order = "%sstory_date" % ('' if order == 'oldest' else '-')
@ -969,10 +970,11 @@ def load_river_stories__redis(request):
if not user.profile.is_premium:
message = "The full River of News is a premium feature."
if page > 1:
stories = []
else:
stories = stories[:5]
code = 0
# if page > 1:
# stories = []
# else:
# stories = stories[:5]
diff = time.time() - start
timediff = round(float(diff), 2)
logging.user(request, "~FYLoading ~FCriver stories~FY: ~SBp%s~SN (%s/%s "
@ -983,7 +985,8 @@ def load_river_stories__redis(request):
# import random
# time.sleep(random.randint(0, 6))
return dict(message=message,
return dict(code=code,
message=message,
stories=stories,
classifiers=classifiers,
elapsed_time=timediff,
@ -1286,9 +1289,11 @@ def mark_story_as_unread(request):
def mark_feed_as_read(request):
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
feed_ids = request.REQUEST.getlist('feed_id')
cutoff_timestamp = int(request.REQUEST.get('cutoff_timestamp', 0))
multiple = len(feed_ids) > 1
code = 1
errors = []
cutoff_date = datetime.datetime.fromtimestamp(cutoff_timestamp) if cutoff_timestamp else None
for feed_id in feed_ids:
if 'social:' in feed_id:
@ -1315,8 +1320,8 @@ def mark_feed_as_read(request):
continue
try:
marked_read = sub.mark_feed_read()
if marked_read:
marked_read = sub.mark_feed_read(cutoff_date=cutoff_date)
if marked_read and not multiple:
r.publish(request.user.username, 'feed:%s' % feed_id)
except IntegrityError, e:
errors.append("Could not mark feed as read: %s" % e)
@ -1324,6 +1329,7 @@ def mark_feed_as_read(request):
if multiple:
logging.user(request, "~FMMarking ~SB%s~SN feeds as read" % len(feed_ids))
r.publish(request.user.username, 'refresh:%s' % ','.join(feed_ids))
return dict(code=code, errors=errors)
@ -1360,6 +1366,10 @@ def add_url(request):
folder=folder, auto_active=auto_active,
skip_fetch=skip_fetch)
feed = us and us.feed
if feed:
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
r.publish(request.user.username, 'reload:%s' % feed.pk)
return dict(code=code, message=message, feed=feed)
@ -1376,6 +1386,8 @@ def add_folder(request):
message = ""
user_sub_folders_object, _ = UserSubscriptionFolders.objects.get_or_create(user=request.user)
user_sub_folders_object.add_folder(parent_folder, folder)
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
r.publish(request.user.username, 'reload:feeds')
else:
code = -1
message = "Gotta write in a folder name."
@ -1397,6 +1409,9 @@ def delete_feed(request):
if feed:
feed[0].count_subscribers()
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
r.publish(request.user.username, 'reload:feeds')
return dict(code=1, message="Removed %s from '%s'." % (feed, in_folder))
@ajax_login_required
@ -1435,6 +1450,9 @@ def delete_folder(request):
user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user)
user_sub_folders.delete_folder(folder_to_delete, in_folder, feed_ids_in_folder)
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
r.publish(request.user.username, 'reload:feeds')
return dict(code=1)
@ajax_login_required
@ -1480,6 +1498,9 @@ def move_feed_to_folder(request):
user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user)
user_sub_folders = user_sub_folders.move_feed_to_folder(feed_id, in_folder=in_folder, to_folder=to_folder)
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
r.publish(request.user.username, 'reload:feeds')
return dict(code=1, folders=json.decode(user_sub_folders.folders))
@ -1492,6 +1513,9 @@ def move_folder_to_folder(request):
user_sub_folders = get_object_or_404(UserSubscriptionFolders, user=request.user)
user_sub_folders = user_sub_folders.move_folder_to_folder(folder_name, in_folder=in_folder, to_folder=to_folder)
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
r.publish(request.user.username, 'reload:feeds')
return dict(code=1, folders=json.decode(user_sub_folders.folders))
@ -1595,7 +1619,10 @@ def save_feed_chooser(request):
request.user.profile.queue_new_feeds()
request.user.profile.refresh_stale_feeds(exclude_new=True)
r = redis.Redis(connection_pool=settings.REDIS_PUBSUB_POOL)
r.publish(request.user.username, 'reload:feeds')
logging.user(request, "~BB~FW~SBActivated standard account: ~FC%s~SN/~SB%s" % (
activated,
usersubs.count()

View file

@ -867,7 +867,7 @@ class MSocialSubscription(mongo.Document):
}
def get_stories(self, offset=0, limit=6, order='newest', read_filter='all',
withscores=False, hashes_only=False):
withscores=False, hashes_only=False, cutoff_date=None):
r = redis.Redis(connection_pool=settings.REDIS_STORY_HASH_POOL)
ignore_user_stories = False
@ -892,6 +892,9 @@ class MSocialSubscription(mongo.Document):
current_time = int(time.time() + 60*60*24)
mark_read_time = int(time.mktime(self.mark_read_date.timetuple())) + 1
if cutoff_date:
mark_read_time = int(time.mktime(cutoff_date.timetuple())) + 1
if order == 'oldest':
byscorefunc = r.zrangebyscore
min_score = mark_read_time
@ -1058,29 +1061,39 @@ class MSocialSubscription(mongo.Document):
# XXX TODO: Real-time notification, just for this user
return data
def mark_feed_read(self):
latest_story_date = datetime.datetime.utcnow()
def mark_feed_read(self, cutoff_date=None):
UNREAD_CUTOFF = datetime.datetime.utcnow() - datetime.timedelta(days=settings.DAYS_OF_UNREAD)
# Use the latest story to get last read time.
latest_shared_story = MSharedStory.objects(user_id=self.subscription_user_id,
shared_date__gte=UNREAD_CUTOFF
).order_by('shared_date').only('shared_date').first()
if latest_shared_story:
latest_story_date = latest_shared_story['shared_date'] + datetime.timedelta(seconds=1)
self.last_read_date = latest_story_date
self.mark_read_date = latest_story_date
self.unread_count_negative = 0
self.unread_count_positive = 0
self.unread_count_neutral = 0
self.unread_count_updated = datetime.datetime.utcnow()
self.oldest_unread_story_date = latest_story_date
recount = True
if cutoff_date:
cutoff_date = cutoff_date + datetime.timedelta(seconds=1)
else:
# Use the latest story to get last read time.
latest_shared_story = MSharedStory.objects(user_id=self.subscription_user_id,
shared_date__gte=UNREAD_CUTOFF
).order_by('shared_date').only('shared_date').first()
if latest_shared_story:
cutoff_date = latest_shared_story['shared_date'] + datetime.timedelta(seconds=1)
else:
cutoff_date = datetime.datetime.utcnow()
recount = False
self.last_read_date = cutoff_date
self.mark_read_date = cutoff_date
self.oldest_unread_story_date = cutoff_date
if not recount:
self.unread_count_negative = 0
self.unread_count_positive = 0
self.unread_count_neutral = 0
self.unread_count_updated = datetime.datetime.utcnow()
self.needs_unread_recalc = False
else:
self.needs_unread_recalc = True
# Manually mark all shared stories as read.
unread_story_hashes = self.get_stories(read_filter='unread', limit=500, hashes_only=True)
unread_story_hashes = self.get_stories(read_filter='unread', limit=500, hashes_only=True,
cutoff_date=cutoff_date)
self.mark_story_ids_as_read(unread_story_hashes, mark_all_read=True)
self.needs_unread_recalc = False
self.save()

View file

@ -137,7 +137,7 @@
<string name="add_facebook">Add Facebook friends</string>
<string name="need_to_login"><u>I need to log in!</u></string>
<string name="need_to_register"><u>I need to register</u></string>
<string name="wonderful_things">Wonderful things are happening at Newsblur. Add our blog for the latest news.</string>
<string name="wonderful_things">Wonderful things are happening at NewsBlur. Add our blog for the latest news.</string>
<string name="addfollow_add_newsblur">Follow the NewsBlur blog</string>
<string name="addfollow_add_popular">Follow Popular Stories</string>
<string name="add_follow">All Done!</string>

View file

@ -175,7 +175,7 @@ public class SyncService extends IntentService {
Log.d( this.getClass().getName(), "Sync Intent complete");
} catch (Exception e) {
Log.e(this.getClass().getName(), "Couldn't synchronise with Newsblur servers: " + e.getMessage(), e.getCause());
Log.e(this.getClass().getName(), "Couldn't synchronise with NewsBlur servers: " + e.getMessage(), e.getCause());
e.printStackTrace();
} finally {
if (receiver != null) {

View file

@ -7,10 +7,9 @@
//
#import <UIKit/UIKit.h>
#import "OHAttributedLabel.h"
@interface ActivityCell : UITableViewCell {
OHAttributedLabel *activityLabel;
UILabel *activityLabel;
UIImageView *faviconView;
int topMargin;
int bottomMargin;
@ -19,7 +18,7 @@
int avatarSize;
}
@property (nonatomic, strong) OHAttributedLabel *activityLabel;
@property (nonatomic, strong) UILabel *activityLabel;
@property (nonatomic, strong) UIImageView *faviconView;
@property (readwrite) int topMargin;
@property (readwrite) int bottomMargin;

View file

@ -7,7 +7,6 @@
//
#import "ActivityCell.h"
#import "NSAttributedString+Attributes.h"
#import "UIImageView+AFNetworking.h"
@implementation ActivityCell
@ -31,9 +30,8 @@
self.faviconView = favicon;
[self.contentView addSubview:favicon];
OHAttributedLabel *activity = [[OHAttributedLabel alloc] initWithFrame:CGRectZero];
UILabel *activity = [[UILabel alloc] initWithFrame:CGRectZero];
activity.backgroundColor = [UIColor whiteColor];
activity.automaticallyAddLinksForType = NO;
self.activityLabel = activity;
[self.contentView addSubview:activity];
@ -61,13 +59,16 @@
labelRect.size.width = contentRect.size.width - leftMargin - avatarSize - leftMargin - rightMargin;
labelRect.size.height = contentRect.size.height - topMargin - bottomMargin;
self.activityLabel.frame = labelRect;
[self.activityLabel sizeToFit];
}
- (int)setActivity:(NSDictionary *)activity withUserProfile:(NSDictionary *)userProfile withWidth:(int)width {
// must set the height again for dynamic height in heightForRowAtIndexPath in
// must set the height again for dynamic height in heightForRowAtIndexPath in
CGRect activityLabelRect = self.activityLabel.bounds;
activityLabelRect.size.width = width - leftMargin - avatarSize - leftMargin - rightMargin;
self.activityLabel.frame = activityLabelRect;
self.activityLabel.numberOfLines = 0;
self.faviconView.frame = CGRectMake(leftMargin, topMargin, avatarSize, avatarSize);
NSString *category = [activity objectForKey:@"category"];
@ -120,15 +121,15 @@
txt = [NSString stringWithFormat:@"%@ followed %@.", username, withUserUsername];
} else if ([category isEqualToString:@"comment_reply"]) {
withUserUsername = [[activity objectForKey:@"with_user"] objectForKey:@"username"];
txt = [NSString stringWithFormat:@"%@ replied to %@: \n%@", username, withUserUsername, comment];
txt = [NSString stringWithFormat:@"%@ replied to %@: \n \n%@", username, withUserUsername, comment];
} else if ([category isEqualToString:@"comment_like"]) {
withUserUsername = [[activity objectForKey:@"with_user"] objectForKey:@"username"];
txt = [NSString stringWithFormat:@"%@ favorited %@'s comment on %@:\n%@", username, withUserUsername, title, comment];
txt = [NSString stringWithFormat:@"%@ favorited %@'s comment on %@:\n \n%@", username, withUserUsername, title, comment];
} else if ([category isEqualToString:@"sharedstory"]) {
if ([content class] == [NSNull class] || [content isEqualToString:@""] || content == nil) {
txt = [NSString stringWithFormat:@"%@ shared %@.", username, title];
} else {
txt = [NSString stringWithFormat:@"%@ shared %@:\n%@", username, title, comment];
txt = [NSString stringWithFormat:@"%@ shared %@:\n \n%@", username, title, comment];
}
} else if ([category isEqualToString:@"star"]) {
@ -139,38 +140,60 @@
txt = [NSString stringWithFormat:@"You signed up for NewsBlur."];
}
NSString *txtWithTime = [NSString stringWithFormat:@"%@\n%@", txt, time];
NSMutableAttributedString* attrStr = [NSMutableAttributedString attributedStringWithString:txtWithTime];
NSString *txtWithTime = [NSString stringWithFormat:@"%@\n \n%@", txt, time];
NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithString:txtWithTime];
// for those calls we don't specify a range so it affects the whole string
[attrStr setFont:[UIFont fontWithName:@"Helvetica" size:14]];
[attrStr setTextColor:UIColorFromRGB(0x333333)];
[attrStr setAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Helvetica" size:13]} range:NSMakeRange(0, [txtWithTime length])];
if (self.highlighted) {
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0xffffff)} range:NSMakeRange(0, [txtWithTime length])];
} else {
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x333333)} range:NSMakeRange(0, [txtWithTime length])];
}
if (![username isEqualToString:@"You"]){
[attrStr setTextColor:UIColorFromRGB(NEWSBLUR_LINK_COLOR) range:[txtWithTime rangeOfString:username]];
[attrStr setTextBold:YES range:[txt rangeOfString:username]];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(NEWSBLUR_LINK_COLOR)} range:[txtWithTime rangeOfString:username]];
[attrStr addAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13]} range:[txtWithTime rangeOfString:username]];
}
if (withUserUsername.length) {
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(NEWSBLUR_LINK_COLOR)} range:[txtWithTime rangeOfString:withUserUsername]];
[attrStr addAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13]} range:[txtWithTime rangeOfString:withUserUsername]];
}
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(NEWSBLUR_LINK_COLOR)} range:[txtWithTime rangeOfString:title]];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x666666)} range:[txtWithTime rangeOfString:comment]];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x999999)} range:[txtWithTime rangeOfString:time]];
[attrStr addAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Helvetica" size:11]} range:[txtWithTime rangeOfString:time]];
NSMutableParagraphStyle* style= [NSMutableParagraphStyle new];
style.lineBreakMode = NSLineBreakByWordWrapping;
[attrStr addAttributes:@{NSParagraphStyleAttributeName: style} range:NSMakeRange(0, [txtWithTime length])];
NSRange commentRange = [txtWithTime rangeOfString:comment];
if (commentRange.location != NSNotFound) {
NSLog(@"Spacing: %@", comment);
commentRange.location -= 2;
commentRange.length = 1;
if ([[txtWithTime substringWithRange:commentRange] isEqualToString:@" "]) {
[attrStr addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:4.0f]
range:commentRange];
}
}
[attrStr setTextColor:UIColorFromRGB(NEWSBLUR_LINK_COLOR) range:[txtWithTime rangeOfString:title]];
if(withUserUsername.length) {
[attrStr setTextColor:UIColorFromRGB(NEWSBLUR_LINK_COLOR) range:[txtWithTime rangeOfString:withUserUsername]];
[attrStr setTextBold:YES range:[txtWithTime rangeOfString:withUserUsername]];
NSRange dateRange = [txtWithTime rangeOfString:time];
if (dateRange.location != NSNotFound) {
dateRange.location -= 2;
dateRange.length = 1;
[attrStr addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:4.0f]
range:dateRange];
}
[attrStr setTextColor:UIColorFromRGB(0x666666) range:[txtWithTime rangeOfString:comment]];
[attrStr setTextColor:UIColorFromRGB(0x999999) range:[txtWithTime rangeOfString:time]];
[attrStr setFont:[UIFont fontWithName:@"Helvetica" size:10] range:[txtWithTime rangeOfString:time]];
[attrStr setTextAlignment:kCTLeftTextAlignment lineBreakMode:kCTLineBreakByWordWrapping lineHeight:4];
self.activityLabel.attributedText = attrStr;
[self.activityLabel sizeToFit];
int height = self.activityLabel.frame.size.height;
return MAX(height, self.faviconView.frame.size.height);
return MAX(height + topMargin + bottomMargin, self.faviconView.frame.size.height + topMargin + bottomMargin);
}
- (NSString *)stripFormatting:(NSString *)str {

View file

@ -24,7 +24,8 @@
@synthesize pageFinished;
@synthesize activitiesPage;
#define MINIMUM_ACTIVITY_HEIGHT 48 + 30
#define MINIMUM_ACTIVITY_HEIGHT_IPAD 78
#define MINIMUM_ACTIVITY_HEIGHT_IPHONE 54
- (id)initWithFrame:(CGRect)frame
{
@ -172,8 +173,15 @@
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
int activitiesCount = [appDelegate.userActivitiesArray count];
int minimumHeight;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
minimumHeight = MINIMUM_ACTIVITY_HEIGHT_IPAD;
} else {
minimumHeight = MINIMUM_ACTIVITY_HEIGHT_IPHONE;
}
if (indexPath.row >= activitiesCount) {
return MINIMUM_ACTIVITY_HEIGHT;
return minimumHeight;
}
id activityCell;
@ -189,10 +197,8 @@
int height = [activityCell setActivity:[appDelegate.userActivitiesArray
objectAtIndex:(indexPath.row)]
withUserProfile:userProfile
withWidth:self.frame.size.width - 20] + 30;
withWidth:self.frame.size.width - 20];
return height;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -223,8 +229,7 @@
NSString *category = [activitiy objectForKey:@"category"];
if ([category isEqualToString:@"follow"]) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else if ([category isEqualToString:@"star"] ||
[category isEqualToString:@"signup"]){
} else if ([category isEqualToString:@"signup"]){
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
} else {
@ -283,6 +288,12 @@
withUser:[activity objectForKey:@"with_user"]
showFindingStory:YES];
appDelegate.tryFeedCategory = category;
} else if ([category isEqualToString:@"star"]) {
NSString *contentIdStr = [NSString stringWithFormat:@"%@",
[activity objectForKey:@"content_id"]];
[appDelegate loadStarredDetailViewWithStory:contentIdStr
showFindingStory:YES];
appDelegate.tryFeedCategory = category;
} else if ([category isEqualToString:@"feedsub"]) {
NSString *feedIdStr = [NSString stringWithFormat:@"%@",
[activity objectForKey:@"feed_id"]];
@ -310,7 +321,12 @@
if (self.pageFinished) {
UIImage *img = [UIImage imageNamed:@"fleuron.png"];
UIImageView *fleuron = [[UIImageView alloc] initWithImage:img];
int height = MINIMUM_ACTIVITY_HEIGHT;
int height;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
height = MINIMUM_ACTIVITY_HEIGHT_IPAD;
} else {
height = MINIMUM_ACTIVITY_HEIGHT_IPHONE;
}
fleuron.frame = CGRectMake(0, 0, self.frame.size.width, height);
fleuron.contentMode = UIViewContentModeCenter;

View file

@ -368,7 +368,7 @@
- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component {
return [[self folders] count];
return [[self folders] count] + 1;
}
- (NSString *)pickerView:(UIPickerView *)pickerView
@ -377,7 +377,7 @@ numberOfRowsInComponent:(NSInteger)component {
if (row == 0) {
return @"— Top Level —";
} else {
return [[self folders] objectAtIndex:row];
return [[self folders] objectAtIndex:row-1];
}
}
@ -388,15 +388,24 @@ numberOfRowsInComponent:(NSInteger)component {
if (row == 0) {
folder_title = @"— Top Level —";
} else {
folder_title = [[self folders] objectAtIndex:row];
folder_title = [[self folders] objectAtIndex:row-1];
}
[inFolderInput setText:folder_title];
}
- (void)showFolderPicker {
if (![[self folders] count]) return;
[siteAddressInput resignFirstResponder];
[addFolderInput resignFirstResponder];
[inFolderInput setInputView:folderPicker];
[folderPicker selectRow:0 inComponent:0 animated:NO];
for (int i=0; i < [[self folders] count]; i++) {
if ([[[self folders] objectAtIndex:i] isEqualToString:inFolderInput.text]) {
[folderPicker selectRow:i+1 inComponent:0 animated:NO];
break;
}
}
if (folderPicker.frame.origin.y >= self.view.bounds.size.height) {
folderPicker.hidden = NO;
[UIView animateWithDuration:.35 animations:^{

View file

@ -110,7 +110,7 @@
appDelegate.userInteractionsArray = nil;
[self.interactionsModule.interactionsTable reloadData];
[self.interactionsModule.interactionsTable scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[self.interactionsModule fetchInteractionsDetail:1];
[self.interactionsModule fetchInteractionsDetail:1];
}
# pragma mark

View file

@ -116,7 +116,6 @@
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[self checkScroll];
[appDelegate.storyPageControl refreshPages];
}
- (void)viewWillAppear:(BOOL)animated {
@ -787,6 +786,7 @@
FeedDetailTableCell *cell = (FeedDetailTableCell *)[self.storyTitlesTable cellForRowAtIndexPath:indexPath];
[self loadStory:cell atRow:indexPath.row];
[MBProgressHUD hideHUDForView:self.view animated:YES];
// found the story, reset the two flags.
// appDelegate.tryFeedStoryId = nil;
appDelegate.inFindingStoryMode = NO;
@ -1056,8 +1056,6 @@
- (void)changeIntelligence:(NSInteger)newLevel {
NSInteger previousLevel = [appDelegate selectedIntelligence];
NSMutableArray *insertIndexPaths = [NSMutableArray array];
NSMutableArray *deleteIndexPaths = [NSMutableArray array];
if (newLevel == previousLevel) return;
@ -1070,48 +1068,7 @@
[appDelegate calculateStoryLocations];
}
for (int i=0; i < appDelegate.storyLocationsCount; i++) {
int location = [[[appDelegate activeFeedStoryLocations] objectAtIndex:i] intValue];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
NSDictionary *story = [appDelegate.activeFeedStories objectAtIndex:location];
int score = [NewsBlurAppDelegate computeStoryScore:[story objectForKey:@"intelligence"]];
if (previousLevel == -1) {
if (newLevel == 0 && score == -1) {
[deleteIndexPaths addObject:indexPath];
} else if (newLevel == 1 && score < 1) {
[deleteIndexPaths addObject:indexPath];
}
} else if (previousLevel == 0) {
if (newLevel == -1 && score == -1) {
[insertIndexPaths addObject:indexPath];
} else if (newLevel == 1 && score == 0) {
[deleteIndexPaths addObject:indexPath];
}
} else if (previousLevel == 1) {
if (newLevel == 0 && score == 0) {
[insertIndexPaths addObject:indexPath];
} else if (newLevel == -1 && score < 1) {
[insertIndexPaths addObject:indexPath];
}
}
}
if (newLevel > previousLevel) {
[appDelegate setSelectedIntelligence:newLevel];
[appDelegate calculateStoryLocations];
}
[self.storyTitlesTable beginUpdates];
if ([deleteIndexPaths count] > 0) {
[self.storyTitlesTable deleteRowsAtIndexPaths:deleteIndexPaths
withRowAnimation:UITableViewRowAnimationNone];
}
if ([insertIndexPaths count] > 0) {
[self.storyTitlesTable insertRowsAtIndexPaths:insertIndexPaths
withRowAnimation:UITableViewRowAnimationNone];
}
[self.storyTitlesTable endUpdates];
[self.storyTitlesTable reloadData];
}
- (NSDictionary *)getStoryAtRow:(NSInteger)indexPathRow {

View file

@ -33,7 +33,7 @@
self.nextButton = next;
self.navigationItem.rightBarButtonItem = next;
self.navigationItem.title = @"All Done!";
self.navigationItem.title = @"All Done";
}
- (void)viewDidUnload
@ -50,7 +50,8 @@
}
- (void)viewDidAppear:(BOOL)animated {
[self addSite:@"http://blog.newsblur.com/rss"];
[self addPopular];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

View file

@ -2,17 +2,17 @@
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1552</int>
<string key="IBDocument.SystemVersion">12C3006</string>
<string key="IBDocument.SystemVersion">12F37</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.34</string>
<string key="IBDocument.HIToolboxVersion">625.00</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">2083</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
<string>IBUIButton</string>
<string>IBUIImageView</string>
<string>IBUILabel</string>
<string>IBUIView</string>
</array>
@ -38,18 +38,18 @@
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUILabel" id="804223306">
<reference key="NSNextResponder" ref="874391841"/>
<int key="NSvFlags">303</int>
<string key="NSFrame">{{70, 86}, {400, 100}}</string>
<int key="NSvFlags">295</int>
<string key="NSFrame">{{20, 20}, {500, 54}}</string>
<reference key="NSSuperview" ref="874391841"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="754909752"/>
<reference key="NSNextKeyView" ref="124119852"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<string key="IBUIText">Keep up-to-date with NewsBlur</string>
<string key="IBUIText">Thanks for trying out NewsBlur!</string>
<object class="NSColor" key="IBUITextColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MCAwIDAAA</bytes>
@ -65,86 +65,61 @@
<float key="IBUIMinimumFontSize">10</float>
<int key="IBUINumberOfLines">7</int>
<int key="IBUITextAlignment">1</int>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<object class="IBUIFontDescription" key="IBUIFontDescription" id="938669415">
<int key="type">1</int>
<double key="pointSize">22</double>
</object>
<object class="NSFont" key="IBUIFont">
<object class="NSFont" key="IBUIFont" id="885580266">
<string key="NSName">Helvetica</string>
<double key="NSSize">22</double>
<int key="NSfFlags">16</int>
</object>
<double key="preferredMaxLayoutWidth">400</double>
<double key="preferredMaxLayoutWidth">500</double>
</object>
<object class="IBUIButton" id="754909752">
<object class="IBUILabel" id="189350887">
<reference key="NSNextResponder" ref="874391841"/>
<int key="NSvFlags">301</int>
<string key="NSFrame">{{143, 220}, {254, 34}}</string>
<reference key="NSSuperview" ref="874391841"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="896197534"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<string key="IBUINormalTitle">Subscribe to the NewsBlur Blog</string>
<reference key="IBUIHighlightedTitleColor" ref="222909269"/>
<object class="NSColor" key="IBUISelectedTitleColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace" id="616856063">
<int key="NSID">2</int>
</object>
</object>
<reference key="IBUINormalTitleColor" ref="222909269"/>
<object class="NSColor" key="IBUINormalTitleShadowColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC42IDAuNiAwLjYAA</bytes>
</object>
<object class="NSCustomResource" key="IBUISelectedBackgroundImage" id="800745180">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">google.png</string>
</object>
<reference key="IBUINormalBackgroundImage" ref="800745180"/>
<object class="IBUIFontDescription" key="IBUIFontDescription" id="1710574">
<int key="type">2</int>
<double key="pointSize">13</double>
</object>
<object class="NSFont" key="IBUIFont" id="961490593">
<string key="NSName">Helvetica-Bold</string>
<double key="NSSize">13</double>
<int key="NSfFlags">16</int>
</object>
</object>
<object class="IBUIButton" id="896197534">
<reference key="NSNextResponder" ref="874391841"/>
<int key="NSvFlags">301</int>
<string key="NSFrame">{{143, 297}, {254, 34}}</string>
<int key="NSvFlags">271</int>
<string key="NSFrame">{{20, 502}, {500, 54}}</string>
<reference key="NSSuperview" ref="874391841"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClipsSubviews">YES</bool>
<int key="IBUIContentMode">7</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<string key="IBUINormalTitle">Subscribe to Popular Stories</string>
<reference key="IBUIHighlightedTitleColor" ref="222909269"/>
<object class="NSColor" key="IBUISelectedTitleColor">
<string key="IBUIText">Remember you always have freedom of choice</string>
<object class="NSColor" key="IBUITextColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<reference key="NSCustomColorSpace" ref="616856063"/>
<bytes key="NSWhite">MC4zMzMzMzMzMzMzAA</bytes>
</object>
<reference key="IBUINormalTitleColor" ref="222909269"/>
<object class="NSColor" key="IBUINormalTitleShadowColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC42IDAuNiAwLjYAA</bytes>
<nil key="IBUIHighlightedColor"/>
<reference key="IBUIShadowColor" ref="222909269"/>
<string key="IBUIShadowOffset">{0, 1}</string>
<int key="IBUIBaselineAdjustment">0</int>
<float key="IBUIMinimumFontSize">10</float>
<int key="IBUINumberOfLines">7</int>
<int key="IBUITextAlignment">1</int>
<reference key="IBUIFontDescription" ref="938669415"/>
<reference key="IBUIFont" ref="885580266"/>
<double key="preferredMaxLayoutWidth">500</double>
</object>
<object class="IBUIImageView" id="124119852">
<reference key="NSNextResponder" ref="874391841"/>
<int key="NSvFlags">279</int>
<string key="NSFrame">{{20, 110}, {500, 351}}</string>
<reference key="NSSuperview" ref="874391841"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="189350887"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<int key="IBUIContentMode">1</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<object class="NSCustomResource" key="IBUIImage">
<string key="NSClassName">NSImage</string>
<string key="NSResourceName">ftux_tree.png</string>
</object>
<reference key="IBUISelectedBackgroundImage" ref="800745180"/>
<reference key="IBUINormalBackgroundImage" ref="800745180"/>
<reference key="IBUIFontDescription" ref="1710574"/>
<reference key="IBUIFont" ref="961490593"/>
</object>
</array>
<string key="NSFrame">{{0, 44}, {540, 576}}</string>
@ -196,33 +171,6 @@
</object>
<int key="connectionID">138</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">tapNewsBlurButton:</string>
<reference key="source" ref="754909752"/>
<reference key="destination" ref="841351856"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">133</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">tapNewsBlurButton:</string>
<reference key="source" ref="896197534"/>
<reference key="destination" ref="841351856"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">135</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">tapPopularButton:</string>
<reference key="source" ref="896197534"/>
<reference key="destination" ref="841351856"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">136</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
@ -247,9 +195,9 @@
<int key="objectID">129</int>
<reference key="object" ref="874391841"/>
<array class="NSMutableArray" key="children">
<reference ref="124119852"/>
<reference ref="189350887"/>
<reference ref="804223306"/>
<reference ref="896197534"/>
<reference ref="754909752"/>
</array>
<reference key="parent" ref="0"/>
</object>
@ -259,13 +207,13 @@
<reference key="parent" ref="874391841"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">58</int>
<reference key="object" ref="754909752"/>
<int key="objectID">139</int>
<reference key="object" ref="189350887"/>
<reference key="parent" ref="874391841"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">134</int>
<reference key="object" ref="896197534"/>
<int key="objectID">140</int>
<reference key="object" ref="124119852"/>
<reference key="parent" ref="874391841"/>
</object>
</array>
@ -276,17 +224,15 @@
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="129.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="134.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="2" key="134.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
<string key="139.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="140.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="57.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="58.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<real value="0.0" key="58.IBUIButtonInspectorSelectedStateConfigurationMetadataKey"/>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">138</int>
<int key="maxID">140</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -556,6 +502,7 @@
<string key="spacer3BarButton">UIBarButtonItem</string>
<string key="spacerBarButton">UIBarButtonItem</string>
<string key="storyTitlesTable">UITableView</string>
<string key="titleImageBarButton">UIBarButtonItem</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="appDelegate">
@ -594,6 +541,10 @@
<string key="name">storyTitlesTable</string>
<string key="candidateClassName">UITableView</string>
</object>
<object class="IBToOneOutletInfo" key="titleImageBarButton">
<string key="name">titleImageBarButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
@ -605,6 +556,7 @@
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="appDelegate">NewsBlurAppDelegate</string>
<string key="loginAsAlert">UIAlertView</string>
<string key="menuTableView">UITableView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
@ -612,6 +564,10 @@
<string key="name">appDelegate</string>
<string key="candidateClassName">NewsBlurAppDelegate</string>
</object>
<object class="IBToOneOutletInfo" key="loginAsAlert">
<string key="name">loginAsAlert</string>
<string key="candidateClassName">UIAlertView</string>
</object>
<object class="IBToOneOutletInfo" key="menuTableView">
<string key="name">menuTableView</string>
<string key="candidateClassName">UITableView</string>
@ -622,33 +578,6 @@
<string key="minorKey">./Classes/FeedsMenuViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">FindSitesViewController</string>
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="appDelegate">NewsBlurAppDelegate</string>
<string key="sitesSearchBar">UISearchBar</string>
<string key="sitesTable">UITableView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="appDelegate">
<string key="name">appDelegate</string>
<string key="candidateClassName">NewsBlurAppDelegate</string>
</object>
<object class="IBToOneOutletInfo" key="sitesSearchBar">
<string key="name">sitesSearchBar</string>
<string key="candidateClassName">UISearchBar</string>
</object>
<object class="IBToOneOutletInfo" key="sitesTable">
<string key="name">sitesTable</string>
<string key="candidateClassName">UITableView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/FindSitesViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">FirstTimeUserAddFriendsViewController</string>
<string key="superclassName">UIViewController</string>
@ -960,6 +889,25 @@
<string key="minorKey">./Classes/FriendsListViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">IASKAppSettingsViewController</string>
<string key="superclassName">UITableViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">delegate</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">delegate</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">delegate</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/IASKAppSettingsViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">InteractionsModule</string>
<string key="superclassName">UIView</string>
@ -1223,7 +1171,6 @@
<string key="feedDetailViewController">FeedDetailViewController</string>
<string key="feedsMenuViewController">FeedsMenuViewController</string>
<string key="feedsViewController">NewsBlurViewController</string>
<string key="findSitesViewController">FindSitesViewController</string>
<string key="firstTimeUserAddFriendsViewController">FirstTimeUserAddFriendsViewController</string>
<string key="firstTimeUserAddNewsBlurViewController">FirstTimeUserAddNewsBlurViewController</string>
<string key="firstTimeUserAddSitesViewController">FirstTimeUserAddSitesViewController</string>
@ -1236,6 +1183,7 @@
<string key="moveSiteViewController">MoveSiteViewController</string>
<string key="navigationController">UINavigationController</string>
<string key="originalStoryViewController">OriginalStoryViewController</string>
<string key="preferencesViewController">IASKAppSettingsViewController</string>
<string key="shareViewController">ShareViewController</string>
<string key="storyDetailViewController">StoryDetailViewController</string>
<string key="storyPageControl">StoryPageControl</string>
@ -1272,10 +1220,6 @@
<string key="name">feedsViewController</string>
<string key="candidateClassName">NewsBlurViewController</string>
</object>
<object class="IBToOneOutletInfo" key="findSitesViewController">
<string key="name">findSitesViewController</string>
<string key="candidateClassName">FindSitesViewController</string>
</object>
<object class="IBToOneOutletInfo" key="firstTimeUserAddFriendsViewController">
<string key="name">firstTimeUserAddFriendsViewController</string>
<string key="candidateClassName">FirstTimeUserAddFriendsViewController</string>
@ -1324,6 +1268,10 @@
<string key="name">originalStoryViewController</string>
<string key="candidateClassName">OriginalStoryViewController</string>
</object>
<object class="IBToOneOutletInfo" key="preferencesViewController">
<string key="name">preferencesViewController</string>
<string key="candidateClassName">IASKAppSettingsViewController</string>
</object>
<object class="IBToOneOutletInfo" key="shareViewController">
<string key="name">shareViewController</string>
<string key="candidateClassName">ShareViewController</string>
@ -1470,7 +1418,7 @@
<string key="superclassName">BaseViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="doCloseOriginalStoryViewController">id</string>
<string key="doOpenActionSheet">id</string>
<string key="doOpenActionSheet:">id</string>
<string key="loadAddress:">id</string>
<string key="webViewGoBack:">id</string>
<string key="webViewGoForward:">id</string>
@ -1481,8 +1429,8 @@
<string key="name">doCloseOriginalStoryViewController</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="doOpenActionSheet">
<string key="name">doOpenActionSheet</string>
<object class="IBActionInfo" key="doOpenActionSheet:">
<string key="name">doOpenActionSheet:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="loadAddress:">
@ -1563,7 +1511,7 @@
</object>
<object class="IBPartialClassDescription">
<string key="className">ShareViewController</string>
<string key="superclassName">UIViewController</string>
<string key="superclassName">BaseViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="doCancelButton:">id</string>
<string key="doReplyToComment:">id</string>
@ -1680,9 +1628,11 @@
<dictionary class="NSMutableDictionary" key="actions">
<string key="doNextUnreadStory">id</string>
<string key="doPreviousStory">id</string>
<string key="openSendToDialog:">id</string>
<string key="showOriginalSubview:">id</string>
<string key="tapProgressBar:">id</string>
<string key="toggleFontSize:">id</string>
<string key="toggleView:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="doNextUnreadStory">
@ -1693,6 +1643,10 @@
<string key="name">doPreviousStory</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="openSendToDialog:">
<string key="name">openSendToDialog:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showOriginalSubview:">
<string key="name">showOriginalSubview:</string>
<string key="candidateClassName">id</string>
@ -1705,18 +1659,25 @@
<string key="name">toggleFontSize:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleView:">
<string key="name">toggleView:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="activity">UIBarButtonItem</string>
<string key="appDelegate">NewsBlurAppDelegate</string>
<string key="bottomPlaceholderToolbar">UIToolbar</string>
<string key="buttonAction">UIBarButtonItem</string>
<string key="buttonNext">UIBarButtonItem</string>
<string key="buttonPrevious">UIBarButtonItem</string>
<string key="buttonNext">UIButton</string>
<string key="buttonPrevious">UIButton</string>
<string key="buttonSend">UIButton</string>
<string key="buttonText">UIButton</string>
<string key="circularProgressView">THCircularProgressView</string>
<string key="fontSettingsButton">UIBarButtonItem</string>
<string key="loadingIndicator">UIActivityIndicatorView</string>
<string key="originalStoryButton">UIBarButtonItem</string>
<string key="pageControl">UIPageControl</string>
<string key="progressView">UIProgressView</string>
<string key="progressView">UIView</string>
<string key="progressViewContainer">UIView</string>
<string key="rightToolbar">TransparentToolbar</string>
<string key="scrollView">UIScrollView</string>
@ -1725,13 +1686,9 @@
<string key="spacer3BarButton">UIBarButtonItem</string>
<string key="spacerBarButton">UIBarButtonItem</string>
<string key="subscribeButton">UIBarButtonItem</string>
<string key="toolbar">UIToolbar</string>
<string key="traverseView">UIView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="activity">
<string key="name">activity</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
<object class="IBToOneOutletInfo" key="appDelegate">
<string key="name">appDelegate</string>
<string key="candidateClassName">NewsBlurAppDelegate</string>
@ -1746,16 +1703,32 @@
</object>
<object class="IBToOneOutletInfo" key="buttonNext">
<string key="name">buttonNext</string>
<string key="candidateClassName">UIBarButtonItem</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonPrevious">
<string key="name">buttonPrevious</string>
<string key="candidateClassName">UIBarButtonItem</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonSend">
<string key="name">buttonSend</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonText">
<string key="name">buttonText</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="circularProgressView">
<string key="name">circularProgressView</string>
<string key="candidateClassName">THCircularProgressView</string>
</object>
<object class="IBToOneOutletInfo" key="fontSettingsButton">
<string key="name">fontSettingsButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
<object class="IBToOneOutletInfo" key="loadingIndicator">
<string key="name">loadingIndicator</string>
<string key="candidateClassName">UIActivityIndicatorView</string>
</object>
<object class="IBToOneOutletInfo" key="originalStoryButton">
<string key="name">originalStoryButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
@ -1766,7 +1739,7 @@
</object>
<object class="IBToOneOutletInfo" key="progressView">
<string key="name">progressView</string>
<string key="candidateClassName">UIProgressView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="progressViewContainer">
<string key="name">progressViewContainer</string>
@ -1800,9 +1773,9 @@
<string key="name">subscribeButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
<object class="IBToOneOutletInfo" key="toolbar">
<string key="name">toolbar</string>
<string key="candidateClassName">UIToolbar</string>
<object class="IBToOneOutletInfo" key="traverseView">
<string key="name">traverseView</string>
<string key="candidateClassName">UIView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@ -1810,6 +1783,14 @@
<string key="minorKey">./Classes/StoryPageControl.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">THCircularProgressView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/THCircularProgressView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">TrainerViewController</string>
<string key="superclassName">BaseViewController</string>
@ -1888,8 +1869,8 @@
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<string key="NS.key.0">google.png</string>
<string key="NS.object.0">{184, 34}</string>
<string key="NS.key.0">ftux_tree.png</string>
<string key="NS.object.0">{495, 600}</string>
</object>
<string key="IBCocoaTouchPluginVersion">2083</string>
</data>

View file

@ -56,7 +56,7 @@
UIBarButtonItem *next = [[UIBarButtonItem alloc] initWithTitle:@"Next step" style:UIBarButtonSystemItemDone target:self action:@selector(tapNextButton)];
self.nextButton = next;
self.nextButton.enabled = NO;
self.nextButton.enabled = YES;
self.navigationItem.rightBarButtonItem = next;
self.navigationItem.title = @"Add Sites";
@ -85,9 +85,9 @@
[self.categoriesTable reloadData];
[self.scrollView setContentSize:CGSizeMake(self.view.frame.size.width, self.tableViewHeight + 100)];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.categoriesTable.frame = CGRectMake((self.view.frame.size.width - 300)/2, 60, self.categoriesTable.frame.size.width, self.tableViewHeight);
self.categoriesTable.frame = CGRectMake((self.view.frame.size.width - 300)/2, 30, self.categoriesTable.frame.size.width, self.tableViewHeight);
} else {
self.categoriesTable.frame = CGRectMake(10, 60, self.categoriesTable.frame.size.width, self.tableViewHeight);
self.categoriesTable.frame = CGRectMake(10, 30, self.categoriesTable.frame.size.width, self.tableViewHeight);
}
NSLog(@"%f height", self.tableViewHeight);
@ -221,33 +221,28 @@
#pragma mark Add Categories
- (void)addCategory:(id)sender {
NSInteger tag = ((UIControl *) sender).tag;
// set the currentButton
self.currentButton_ = (UIButton *)sender;
if (tag == 1000) {
[self tapGoogleReaderButton];
UIButton *button = (UIButton *)sender;
NSLog(@"self.currentButton_.titleLabel.text is %@", self.currentButton_.titleLabel.text);
if (button.selected) {
[self.selectedCategories_ removeObject:self.currentButton_.titleLabel.text];
self.nextButton.enabled = YES;
button.selected = NO;
UIImageView *imageView = (UIImageView*)[button viewWithTag:100];
[imageView removeFromSuperview];
} else {
UIButton *button = (UIButton *)sender;
NSLog(@"self.currentButton_.titleLabel.text is %@", self.currentButton_.titleLabel.text);
if (button.selected) {
[self.selectedCategories_ removeObject:self.currentButton_.titleLabel.text];
self.nextButton.enabled = YES;
button.selected = NO;
UIImageView *imageView = (UIImageView*)[button viewWithTag:100];
[imageView removeFromSuperview];
} else {
[self.selectedCategories_ addObject:self.currentButton_.titleLabel.text];
button.selected = YES;
}
[self.selectedCategories_ addObject:self.currentButton_.titleLabel.text];
button.selected = YES;
}
if (self.googleImportSuccess_) {
self.nextButton.enabled = YES;
} else if (self.selectedCategories_.count) {
self.nextButton.enabled = YES;
} else {
self.nextButton.enabled = NO;
self.nextButton.enabled = YES;
}
[self.categoriesTable reloadData];
@ -285,7 +280,7 @@
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return appDelegate.categories.count + 2;
return appDelegate.categories.count + 1;
}
//- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
@ -296,11 +291,9 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return 1;
} else if (section == 1) {
return 0;
} else {
NSDictionary *category = [appDelegate.categories objectAtIndex:section - 2];
NSDictionary *category = [appDelegate.categories objectAtIndex:section - 1];
NSArray *categorySiteList = [category objectForKey:@"feed_ids"];
return categorySiteList.count;
}
@ -312,16 +305,20 @@
}
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
if (section == 0) {
return 28.0;
}
return 54.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if (section == 1) {
if (section == 0) {
UIView* categoryTitleView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 20.0, 300.0, 34.0)];
UILabel *categoryTitleLabel = [[UILabel alloc] initWithFrame:categoryTitleView.frame];
categoryTitleLabel.text = @"Choose categories to subscribe to:";
categoryTitleLabel.font = [UIFont fontWithName:@"Helvetica" size:19];
categoryTitleLabel.text = @"You can always add your own individual sites.";
categoryTitleLabel.font = [UIFont fontWithName:@"Helvetica" size:14];
[categoryTitleView addSubview:categoryTitleLabel];
categoryTitleLabel.textColor = [UIColor darkGrayColor];
categoryTitleLabel.backgroundColor = [UIColor clearColor];
categoryTitleView.backgroundColor = [UIColor clearColor];
categoryTitleLabel.textAlignment = NSTextAlignmentCenter;
@ -343,25 +340,21 @@
headerBtn.titleLabel.shadowColor = UIColorFromRGB(0x1E5BDB);
headerBtn.titleLabel.shadowOffset = CGSizeMake(0, 1);
NSString *categoryTitle;
if (section == 0) {
categoryTitle = @"Google Reader";
} else {
NSDictionary *category = [appDelegate.categories objectAtIndex:section - 2];
categoryTitle = [category objectForKey:@"title"];
BOOL inSelect = [self.selectedCategories_ containsObject:[NSString stringWithFormat:@"%@", [category objectForKey:@"title"]]];
NSLog(@"inselected %i", inSelect);
if (inSelect) {
headerBtn.selected = YES;
UIImage *checkmark = [UIImage imageNamed:@"258-checkmark"];
UIImageView *checkmarkView = [[UIImageView alloc] initWithImage:checkmark];
checkmarkView.frame = CGRectMake(headerBtn.frame.origin.x + headerBtn.frame.size.width - 24,
8,
16,
16);
checkmarkView.tag = 100;
[headerBtn addSubview:checkmarkView];
}
NSDictionary *category = [appDelegate.categories objectAtIndex:section - 1];
categoryTitle = [category objectForKey:@"title"];
BOOL inSelect = [self.selectedCategories_ containsObject:[NSString stringWithFormat:@"%@", [category objectForKey:@"title"]]];
NSLog(@"inselected %i", inSelect);
if (inSelect) {
headerBtn.selected = YES;
UIImage *checkmark = [UIImage imageNamed:@"258-checkmark"];
UIImageView *checkmarkView = [[UIImageView alloc] initWithImage:checkmark];
checkmarkView.frame = CGRectMake(headerBtn.frame.origin.x + headerBtn.frame.size.width - 24,
8,
16,
16);
checkmarkView.tag = 100;
[headerBtn addSubview:checkmarkView];
}
[headerBtn setTitle:categoryTitle forState:UIControlStateNormal];
@ -383,58 +376,51 @@
NSString *siteTitle;
if (indexPath.section == 0 ) {
siteTitle = @"Import your sites from Google Reader";
cell.siteFavicon = nil;
cell.feedColorBar = nil;
cell.feedColorBarTopBorder = nil;
NSDictionary *category = [appDelegate.categories objectAtIndex:indexPath.section - 1];
NSArray *categorySiteList = [category objectForKey:@"feed_ids"];
NSString * feedId = [NSString stringWithFormat:@"%@", [categorySiteList objectAtIndex:indexPath.row ]];
NSDictionary *feed = [appDelegate.categoryFeeds objectForKey:feedId];
siteTitle = [feed objectForKey:@"feed_title"];
BOOL inSelect = [self.selectedCategories_ containsObject:[NSString stringWithFormat:@"%@", [category objectForKey:@"title"]]];
if (inSelect) {
cell.isRead = NO;
} else {
NSDictionary *category = [appDelegate.categories objectAtIndex:indexPath.section - 2];
NSArray *categorySiteList = [category objectForKey:@"feed_ids"];
NSString * feedId = [NSString stringWithFormat:@"%@", [categorySiteList objectAtIndex:indexPath.row ]];
NSDictionary *feed = [appDelegate.categoryFeeds objectForKey:feedId];
siteTitle = [feed objectForKey:@"feed_title"];
BOOL inSelect = [self.selectedCategories_ containsObject:[NSString stringWithFormat:@"%@", [category objectForKey:@"title"]]];
if (inSelect) {
cell.isRead = NO;
} else {
cell.isRead = YES;
}
// feed color bar border
unsigned int colorBorder = 0;
NSString *faviconColor = [feed valueForKey:@"favicon_color"];
if ([faviconColor class] == [NSNull class]) {
faviconColor = @"505050";
}
NSScanner *scannerBorder = [NSScanner scannerWithString:faviconColor];
[scannerBorder scanHexInt:&colorBorder];
cell.feedColorBar = UIColorFromRGB(colorBorder);
// feed color bar border
NSString *faviconFade = [feed valueForKey:@"favicon_border"];
if ([faviconFade class] == [NSNull class]) {
faviconFade = @"505050";
}
scannerBorder = [NSScanner scannerWithString:faviconFade];
[scannerBorder scanHexInt:&colorBorder];
cell.feedColorBarTopBorder = UIColorFromRGB(colorBorder);
// favicon
NSString *faviconStr = [NSString stringWithFormat:@"%@", [feed valueForKey:@"favicon"]];
NSData *imageData = [NSData dataWithBase64EncodedString:faviconStr];
UIImage *faviconImage = [UIImage imageWithData:imageData];
cell.siteFavicon = faviconImage;
cell.isRead = YES;
}
// feed color bar border
unsigned int colorBorder = 0;
NSString *faviconColor = [feed valueForKey:@"favicon_color"];
if ([faviconColor class] == [NSNull class]) {
faviconColor = @"505050";
}
NSScanner *scannerBorder = [NSScanner scannerWithString:faviconColor];
[scannerBorder scanHexInt:&colorBorder];
cell.feedColorBar = UIColorFromRGB(colorBorder);
// feed color bar border
NSString *faviconFade = [feed valueForKey:@"favicon_border"];
if ([faviconFade class] == [NSNull class]) {
faviconFade = @"505050";
}
scannerBorder = [NSScanner scannerWithString:faviconFade];
[scannerBorder scanHexInt:&colorBorder];
cell.feedColorBarTopBorder = UIColorFromRGB(colorBorder);
// favicon
NSString *faviconStr = [NSString stringWithFormat:@"%@", [feed valueForKey:@"favicon"]];
NSData *imageData = [NSData dataWithBase64EncodedString:faviconStr];
UIImage *faviconImage = [UIImage imageWithData:imageData];
cell.siteFavicon = faviconImage;
cell.opaque = NO;
cell.siteTitle = siteTitle;

View file

@ -2,10 +2,10 @@
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1552</int>
<string key="IBDocument.SystemVersion">12C3006</string>
<string key="IBDocument.SystemVersion">12F37</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.34</string>
<string key="IBDocument.HIToolboxVersion">625.00</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">2083</string>
@ -44,9 +44,10 @@
<object class="IBUITableView" id="1020189204">
<reference key="NSNextResponder" ref="75178207"/>
<int key="NSvFlags">277</int>
<string key="NSFrame">{{120, 80}, {300, 463}}</string>
<string key="NSFrame">{{120, 53}, {300, 490}}</string>
<reference key="NSSuperview" ref="75178207"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
@ -68,7 +69,7 @@
<object class="IBUILabel" id="482977125">
<reference key="NSNextResponder" ref="75178207"/>
<int key="NSvFlags">303</int>
<string key="NSFrame">{{13, 12}, {514, 60}}</string>
<string key="NSFrame">{{0, 12}, {540, 42}}</string>
<reference key="NSSuperview" ref="75178207"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1020189204"/>
@ -78,7 +79,7 @@
<int key="IBUIContentMode">7</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<string key="IBUIText">Let's get some sites to read</string>
<string key="IBUIText">Subscribe to recommend sites:</string>
<object class="NSColor" key="IBUITextColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MCAwIDAAA</bytes>
@ -103,7 +104,7 @@
<double key="NSSize">22</double>
<int key="NSfFlags">16</int>
</object>
<double key="preferredMaxLayoutWidth">514</double>
<double key="preferredMaxLayoutWidth">540</double>
</object>
</array>
<string key="NSFrameSize">{540, 540}</string>
@ -502,6 +503,7 @@
<string key="spacer3BarButton">UIBarButtonItem</string>
<string key="spacerBarButton">UIBarButtonItem</string>
<string key="storyTitlesTable">UITableView</string>
<string key="titleImageBarButton">UIBarButtonItem</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="appDelegate">
@ -540,6 +542,10 @@
<string key="name">storyTitlesTable</string>
<string key="candidateClassName">UITableView</string>
</object>
<object class="IBToOneOutletInfo" key="titleImageBarButton">
<string key="name">titleImageBarButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
@ -551,6 +557,7 @@
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="appDelegate">NewsBlurAppDelegate</string>
<string key="loginAsAlert">UIAlertView</string>
<string key="menuTableView">UITableView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
@ -558,6 +565,10 @@
<string key="name">appDelegate</string>
<string key="candidateClassName">NewsBlurAppDelegate</string>
</object>
<object class="IBToOneOutletInfo" key="loginAsAlert">
<string key="name">loginAsAlert</string>
<string key="candidateClassName">UIAlertView</string>
</object>
<object class="IBToOneOutletInfo" key="menuTableView">
<string key="name">menuTableView</string>
<string key="candidateClassName">UITableView</string>
@ -568,33 +579,6 @@
<string key="minorKey">./Classes/FeedsMenuViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">FindSitesViewController</string>
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="appDelegate">NewsBlurAppDelegate</string>
<string key="sitesSearchBar">UISearchBar</string>
<string key="sitesTable">UITableView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="appDelegate">
<string key="name">appDelegate</string>
<string key="candidateClassName">NewsBlurAppDelegate</string>
</object>
<object class="IBToOneOutletInfo" key="sitesSearchBar">
<string key="name">sitesSearchBar</string>
<string key="candidateClassName">UISearchBar</string>
</object>
<object class="IBToOneOutletInfo" key="sitesTable">
<string key="name">sitesTable</string>
<string key="candidateClassName">UITableView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/FindSitesViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">FirstTimeUserAddFriendsViewController</string>
<string key="superclassName">UIViewController</string>
@ -906,6 +890,25 @@
<string key="minorKey">./Classes/FriendsListViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">IASKAppSettingsViewController</string>
<string key="superclassName">UITableViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">delegate</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">delegate</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">delegate</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/IASKAppSettingsViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">InteractionsModule</string>
<string key="superclassName">UIView</string>
@ -1169,7 +1172,6 @@
<string key="feedDetailViewController">FeedDetailViewController</string>
<string key="feedsMenuViewController">FeedsMenuViewController</string>
<string key="feedsViewController">NewsBlurViewController</string>
<string key="findSitesViewController">FindSitesViewController</string>
<string key="firstTimeUserAddFriendsViewController">FirstTimeUserAddFriendsViewController</string>
<string key="firstTimeUserAddNewsBlurViewController">FirstTimeUserAddNewsBlurViewController</string>
<string key="firstTimeUserAddSitesViewController">FirstTimeUserAddSitesViewController</string>
@ -1182,6 +1184,7 @@
<string key="moveSiteViewController">MoveSiteViewController</string>
<string key="navigationController">UINavigationController</string>
<string key="originalStoryViewController">OriginalStoryViewController</string>
<string key="preferencesViewController">IASKAppSettingsViewController</string>
<string key="shareViewController">ShareViewController</string>
<string key="storyDetailViewController">StoryDetailViewController</string>
<string key="storyPageControl">StoryPageControl</string>
@ -1218,10 +1221,6 @@
<string key="name">feedsViewController</string>
<string key="candidateClassName">NewsBlurViewController</string>
</object>
<object class="IBToOneOutletInfo" key="findSitesViewController">
<string key="name">findSitesViewController</string>
<string key="candidateClassName">FindSitesViewController</string>
</object>
<object class="IBToOneOutletInfo" key="firstTimeUserAddFriendsViewController">
<string key="name">firstTimeUserAddFriendsViewController</string>
<string key="candidateClassName">FirstTimeUserAddFriendsViewController</string>
@ -1270,6 +1269,10 @@
<string key="name">originalStoryViewController</string>
<string key="candidateClassName">OriginalStoryViewController</string>
</object>
<object class="IBToOneOutletInfo" key="preferencesViewController">
<string key="name">preferencesViewController</string>
<string key="candidateClassName">IASKAppSettingsViewController</string>
</object>
<object class="IBToOneOutletInfo" key="shareViewController">
<string key="name">shareViewController</string>
<string key="candidateClassName">ShareViewController</string>
@ -1416,7 +1419,7 @@
<string key="superclassName">BaseViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="doCloseOriginalStoryViewController">id</string>
<string key="doOpenActionSheet">id</string>
<string key="doOpenActionSheet:">id</string>
<string key="loadAddress:">id</string>
<string key="webViewGoBack:">id</string>
<string key="webViewGoForward:">id</string>
@ -1427,8 +1430,8 @@
<string key="name">doCloseOriginalStoryViewController</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="doOpenActionSheet">
<string key="name">doOpenActionSheet</string>
<object class="IBActionInfo" key="doOpenActionSheet:">
<string key="name">doOpenActionSheet:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="loadAddress:">
@ -1509,7 +1512,7 @@
</object>
<object class="IBPartialClassDescription">
<string key="className">ShareViewController</string>
<string key="superclassName">UIViewController</string>
<string key="superclassName">BaseViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="doCancelButton:">id</string>
<string key="doReplyToComment:">id</string>
@ -1626,9 +1629,11 @@
<dictionary class="NSMutableDictionary" key="actions">
<string key="doNextUnreadStory">id</string>
<string key="doPreviousStory">id</string>
<string key="openSendToDialog:">id</string>
<string key="showOriginalSubview:">id</string>
<string key="tapProgressBar:">id</string>
<string key="toggleFontSize:">id</string>
<string key="toggleView:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="doNextUnreadStory">
@ -1639,6 +1644,10 @@
<string key="name">doPreviousStory</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="openSendToDialog:">
<string key="name">openSendToDialog:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showOriginalSubview:">
<string key="name">showOriginalSubview:</string>
<string key="candidateClassName">id</string>
@ -1651,18 +1660,25 @@
<string key="name">toggleFontSize:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleView:">
<string key="name">toggleView:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="activity">UIBarButtonItem</string>
<string key="appDelegate">NewsBlurAppDelegate</string>
<string key="bottomPlaceholderToolbar">UIToolbar</string>
<string key="buttonAction">UIBarButtonItem</string>
<string key="buttonNext">UIBarButtonItem</string>
<string key="buttonPrevious">UIBarButtonItem</string>
<string key="buttonNext">UIButton</string>
<string key="buttonPrevious">UIButton</string>
<string key="buttonSend">UIButton</string>
<string key="buttonText">UIButton</string>
<string key="circularProgressView">THCircularProgressView</string>
<string key="fontSettingsButton">UIBarButtonItem</string>
<string key="loadingIndicator">UIActivityIndicatorView</string>
<string key="originalStoryButton">UIBarButtonItem</string>
<string key="pageControl">UIPageControl</string>
<string key="progressView">UIProgressView</string>
<string key="progressView">UIView</string>
<string key="progressViewContainer">UIView</string>
<string key="rightToolbar">TransparentToolbar</string>
<string key="scrollView">UIScrollView</string>
@ -1671,13 +1687,9 @@
<string key="spacer3BarButton">UIBarButtonItem</string>
<string key="spacerBarButton">UIBarButtonItem</string>
<string key="subscribeButton">UIBarButtonItem</string>
<string key="toolbar">UIToolbar</string>
<string key="traverseView">UIView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="activity">
<string key="name">activity</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
<object class="IBToOneOutletInfo" key="appDelegate">
<string key="name">appDelegate</string>
<string key="candidateClassName">NewsBlurAppDelegate</string>
@ -1692,16 +1704,32 @@
</object>
<object class="IBToOneOutletInfo" key="buttonNext">
<string key="name">buttonNext</string>
<string key="candidateClassName">UIBarButtonItem</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonPrevious">
<string key="name">buttonPrevious</string>
<string key="candidateClassName">UIBarButtonItem</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonSend">
<string key="name">buttonSend</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonText">
<string key="name">buttonText</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="circularProgressView">
<string key="name">circularProgressView</string>
<string key="candidateClassName">THCircularProgressView</string>
</object>
<object class="IBToOneOutletInfo" key="fontSettingsButton">
<string key="name">fontSettingsButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
<object class="IBToOneOutletInfo" key="loadingIndicator">
<string key="name">loadingIndicator</string>
<string key="candidateClassName">UIActivityIndicatorView</string>
</object>
<object class="IBToOneOutletInfo" key="originalStoryButton">
<string key="name">originalStoryButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
@ -1712,7 +1740,7 @@
</object>
<object class="IBToOneOutletInfo" key="progressView">
<string key="name">progressView</string>
<string key="candidateClassName">UIProgressView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="progressViewContainer">
<string key="name">progressViewContainer</string>
@ -1746,9 +1774,9 @@
<string key="name">subscribeButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
<object class="IBToOneOutletInfo" key="toolbar">
<string key="name">toolbar</string>
<string key="candidateClassName">UIToolbar</string>
<object class="IBToOneOutletInfo" key="traverseView">
<string key="name">traverseView</string>
<string key="candidateClassName">UIView</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@ -1756,6 +1784,14 @@
<string key="minorKey">./Classes/StoryPageControl.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">THCircularProgressView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/THCircularProgressView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">TrainerViewController</string>
<string key="superclassName">BaseViewController</string>

View file

@ -7,10 +7,9 @@
//
#import <UIKit/UIKit.h>
#import "OHAttributedLabel.h"
@interface InteractionCell : UITableViewCell {
OHAttributedLabel *interactionLabel;
UILabel *interactionLabel;
UIImageView *avatarView;
int topMargin;
int bottomMargin;
@ -19,7 +18,7 @@
int avatarSize;
}
@property (retain, nonatomic) OHAttributedLabel *interactionLabel;
@property (retain, nonatomic) UILabel *interactionLabel;
@property (retain, nonatomic) UIImageView *avatarView;
@property (readwrite) int topMargin;
@property (readwrite) int bottomMargin;

View file

@ -7,8 +7,8 @@
//
#import "InteractionCell.h"
#import "NSAttributedString+Attributes.h"
#import "UIImageView+AFNetworking.h"
#import <CoreText/CoreText.h>
@implementation InteractionCell
@ -31,9 +31,9 @@
self.avatarView = avatar;
[self.contentView addSubview:avatar];
OHAttributedLabel *interaction = [[OHAttributedLabel alloc] initWithFrame:CGRectZero];
UILabel *interaction = [[UILabel alloc] initWithFrame:CGRectZero];
interaction.backgroundColor = [UIColor whiteColor];
interaction.automaticallyAddLinksForType = NO;
// interaction.automaticallyAddLinksForType = NO;
self.interactionLabel = interaction;
[self.contentView addSubview:interaction];
@ -64,6 +64,7 @@
labelRect.size.width = contentRect.size.width - leftMargin - avatarSize - leftMargin - rightMargin;
labelRect.size.height = contentRect.size.height - topMargin - bottomMargin;
self.interactionLabel.frame = labelRect;
[self.interactionLabel sizeToFit];
}
@ -74,17 +75,16 @@
interactionLabelRect.size.height = 300;
self.interactionLabel.frame = interactionLabelRect;
self.interactionLabel.numberOfLines = 0;
self.avatarView.frame = CGRectMake(leftMargin, topMargin, avatarSize, avatarSize);
// UIImage *placeholder = [UIImage imageNamed:@"user_light"];
// this is for the rare instance when the with_user doesn't return anything
if ([[interaction objectForKey:@"with_user"] class] == [NSNull class]) {
return 1;
}
[self.avatarView setImageWithURL:[NSURL URLWithString:[[interaction objectForKey:@"with_user"] objectForKey:@"photo_url"]]
placeholderImage:nil];
placeholderImage:nil ];
NSString *category = [interaction objectForKey:@"category"];
NSString *content = [interaction objectForKey:@"content"];
@ -97,50 +97,72 @@
if ([category isEqualToString:@"follow"]) {
txt = [NSString stringWithFormat:@"%@ is now following you.", username];
} else if ([category isEqualToString:@"comment_reply"]) {
txt = [NSString stringWithFormat:@"%@ replied to your comment on %@:\n%@", username, title, comment];
txt = [NSString stringWithFormat:@"%@ replied to your comment on %@:\n \n%@", username, title, comment];
} else if ([category isEqualToString:@"reply_reply"]) {
txt = [NSString stringWithFormat:@"%@ replied to your reply on %@:\n%@", username, title, comment];
txt = [NSString stringWithFormat:@"%@ replied to your reply on %@:\n \n%@", username, title, comment];
} else if ([category isEqualToString:@"story_reshare"]) {
if ([content isEqualToString:@""] || content == nil) {
txt = [NSString stringWithFormat:@"%@ re-shared %@.", username, title];
} else {
txt = [NSString stringWithFormat:@"%@ re-shared %@:\n%@", username, title, comment];
txt = [NSString stringWithFormat:@"%@ re-shared %@:\n \n%@", username, title, comment];
}
} else if ([category isEqualToString:@"comment_like"]) {
txt = [NSString stringWithFormat:@"%@ favorited your comments on %@:\n%@", username, title, comment];
txt = [NSString stringWithFormat:@"%@ favorited your comments on %@:\n \n%@", username, title, comment];
}
NSString *txtWithTime = [NSString stringWithFormat:@"%@\n%@", txt, time];
NSMutableAttributedString* attrStr = [NSMutableAttributedString attributedStringWithString:txtWithTime];
NSString *txtWithTime = [NSString stringWithFormat:@"%@\n \n%@", txt, time];
NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithString:txtWithTime];
// for those calls we don't specify a range so it affects the whole string
[attrStr setFont:[UIFont fontWithName:@"Helvetica" size:14]];
NSMutableParagraphStyle* style = [NSMutableParagraphStyle new];
style.lineBreakMode = NSLineBreakByWordWrapping;
style.alignment = NSTextAlignmentLeft;
style.lineSpacing = 1.0f;
[attrStr setAttributes:@{NSParagraphStyleAttributeName: style} range:NSMakeRange(0, [txtWithTime length])];
[attrStr addAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Helvetica" size:13]} range:NSMakeRange(0, [txtWithTime length])];
if (self.highlighted) {
[attrStr setTextColor:UIColorFromRGB(0xffffff)];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0xffffff)} range:NSMakeRange(0, [txtWithTime length])];
} else {
[attrStr setTextColor:UIColorFromRGB(0x333333)];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x333333)} range:NSMakeRange(0, [txtWithTime length])];
}
if (![username isEqualToString:@"You"]){
[attrStr setTextColor:UIColorFromRGB(NEWSBLUR_LINK_COLOR) range:[txtWithTime rangeOfString:username]];
[attrStr setTextBold:YES range:[txt rangeOfString:username]];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(NEWSBLUR_LINK_COLOR)} range:[txtWithTime rangeOfString:username]];
[attrStr addAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13]} range:[txtWithTime rangeOfString:username]];
}
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(NEWSBLUR_LINK_COLOR)} range:[txtWithTime rangeOfString:title]];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x666666)} range:[txtWithTime rangeOfString:comment]];
[attrStr addAttributes:@{NSForegroundColorAttributeName:UIColorFromRGB(0x999999)} range:[txtWithTime rangeOfString:time]];
[attrStr addAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Helvetica" size:11]} range:[txtWithTime rangeOfString:time]];
NSRange commentRange = [txtWithTime rangeOfString:comment];
if (commentRange.location != NSNotFound) {
commentRange.location -= 2;
commentRange.length = 1;
if ([[txtWithTime substringWithRange:commentRange] isEqualToString:@" "]) {
[attrStr addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:6.0f]
range:commentRange];
}
}
[attrStr setTextColor:UIColorFromRGB(NEWSBLUR_LINK_COLOR) range:[txtWithTime rangeOfString:title]];
[attrStr setTextColor:UIColorFromRGB(0x666666) range:[txtWithTime rangeOfString:comment]];
[attrStr setTextColor:UIColorFromRGB(0x999999) range:[txtWithTime rangeOfString:time]];
[attrStr setFont:[UIFont fontWithName:@"Helvetica" size:10] range:[txtWithTime rangeOfString:time]];
[attrStr setTextAlignment:kCTLeftTextAlignment lineBreakMode:kCTLineBreakByWordWrapping lineHeight:4];
self.interactionLabel.attributedText = attrStr;
NSRange dateRange = [txtWithTime rangeOfString:time];
if (dateRange.location != NSNotFound) {
dateRange.location -= 2;
dateRange.length = 1;
[attrStr addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:6.0f]
range:dateRange];
}
self.interactionLabel.attributedText = attrStr;
[self.interactionLabel sizeToFit];
int height = self.interactionLabel.frame.size.height;
return height;
return MAX(height + topMargin + bottomMargin, self.avatarView.frame.size.height + topMargin + bottomMargin);
}
- (NSString *)stripFormatting:(NSString *)str {

View file

@ -13,8 +13,10 @@
#import <QuartzCore/QuartzCore.h>
#import "ASIHTTPRequest.h"
#import "UserProfileViewController.h"
#import "DashboardViewController.h"
#define MINIMUM_INTERACTION_HEIGHT 78
#define MINIMUM_INTERACTION_HEIGHT_IPAD 78
#define MINIMUM_INTERACTION_HEIGHT_IPHONE 54
@implementation InteractionsModule
@ -147,6 +149,10 @@
if (self.interactionsPage == 1) {
appDelegate.userInteractionsArray = confirmedInteractions;
if (![confirmedInteractions count]) {
appDelegate.dashboardViewController.segmentedButton.selectedSegmentIndex = 1;
[appDelegate.dashboardViewController tapSegmentedButton:nil];
}
} else {
appDelegate.userInteractionsArray = [appDelegate.userInteractionsArray arrayByAddingObjectsFromArray:newInteractions];
}
@ -175,8 +181,15 @@
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
int userInteractions = [appDelegate.userInteractionsArray count];
int minimumHeight;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
minimumHeight = MINIMUM_INTERACTION_HEIGHT_IPAD;
} else {
minimumHeight = MINIMUM_INTERACTION_HEIGHT_IPHONE;
}
if (indexPath.row >= userInteractions) {
return MINIMUM_INTERACTION_HEIGHT;
return minimumHeight;
}
InteractionCell *interactionCell;
@ -185,13 +198,9 @@
} else {
interactionCell = [[SmallInteractionCell alloc] init];
}
int height = [interactionCell setInteraction:[appDelegate.userInteractionsArray objectAtIndex:(indexPath.row)] withWidth:self.frame.size.width - 20] + 30;
if (height < MINIMUM_INTERACTION_HEIGHT) {
return MINIMUM_INTERACTION_HEIGHT;
} else {
return height;
}
int height = [interactionCell setInteraction:[appDelegate.userInteractionsArray objectAtIndex:(indexPath.row)] withWidth:self.frame.size.width - 20];
return height;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
@ -230,6 +239,7 @@
// update the cell information
[cell setInteraction:interaction withWidth: self.frame.size.width - 20];
[cell layoutSubviews];
}
return cell;
@ -289,7 +299,13 @@
if (self.pageFinished) {
UIImage *img = [UIImage imageNamed:@"fleuron.png"];
UIImageView *fleuron = [[UIImageView alloc] initWithImage:img];
int height = MINIMUM_INTERACTION_HEIGHT;
int height;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
height = MINIMUM_INTERACTION_HEIGHT_IPAD;
} else {
height = MINIMUM_INTERACTION_HEIGHT_IPHONE;
}
fleuron.frame = CGRectMake(0, 0, self.frame.size.width, height);
fleuron.contentMode = UIViewContentModeCenter;

View file

@ -12,6 +12,10 @@
@class NewsBlurAppDelegate;
@interface FolderTextField : UITextField
@end
@interface MoveSiteViewController : UIViewController
<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource, ASIHTTPRequestDelegate> {
NewsBlurAppDelegate *appDelegate;
@ -25,8 +29,8 @@
- (NSArray *)pickerFolders;
@property (nonatomic) IBOutlet NewsBlurAppDelegate *appDelegate;
@property (nonatomic) IBOutlet UITextField *fromFolderInput;
@property (nonatomic) IBOutlet UITextField *toFolderInput;
@property (nonatomic) IBOutlet FolderTextField *fromFolderInput;
@property (nonatomic) IBOutlet FolderTextField *toFolderInput;
@property (nonatomic) IBOutlet UILabel *titleLabel;
@property (nonatomic) IBOutlet UIBarButtonItem *moveButton;
@ -41,3 +45,4 @@
@property (nonatomic) NSMutableArray *folders;
@end

View file

@ -36,14 +36,14 @@
- (void)viewDidLoad {
UIImageView *folderImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_folder.png"]];
folderImage.frame = CGRectMake(0, 0, 16, 16);
folderImage.frame = CGRectMake(-6, 0, 16, 16);
[toFolderInput setLeftView:folderImage];
[toFolderInput setLeftViewMode:UITextFieldViewModeAlways];
UIImageView *folderImage2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_folder_rss.png"]];
folderImage2.frame = CGRectMake(0, 0, 16, 16);
folderImage2.frame = CGRectMake(-6, 0, 16, 16);
[fromFolderInput setLeftView:folderImage2];
[fromFolderInput setLeftViewMode:UITextFieldViewModeAlways];
navBar.tintColor = [UIColor colorWithRed:0.16f green:0.36f blue:0.46 alpha:0.9];
appDelegate = [NewsBlurAppDelegate sharedAppDelegate];
@ -290,3 +290,20 @@ numberOfRowsInComponent:(NSInteger)component {
}
@end
@implementation FolderTextField
- (CGRect)textRectForBounds:(CGRect)bounds {
int margin = 18;
CGRect inset = CGRectMake(bounds.origin.x + margin, bounds.origin.y, bounds.size.width - margin, bounds.size.height);
return inset;
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
int margin = 18;
CGRect inset = CGRectMake(bounds.origin.x + margin, bounds.origin.y, bounds.size.width - margin, bounds.size.height);
return inset;
}
@end

View file

@ -48,6 +48,8 @@
@property (readwrite) BOOL isSharingStory;
@property (readwrite) BOOL isHidingStory;
@property (readwrite) BOOL feedDetailIsVisible;
@property (readwrite) BOOL keyboardIsShown;
@property (readwrite) UIDeviceOrientation rotatingToOrientation;
@property (nonatomic, strong) UIPopoverController *popoverController;
@ -65,6 +67,7 @@
@synthesize storyPageControl;
@synthesize shareViewController;
@synthesize feedDetailIsVisible;
@synthesize keyboardIsShown;
@synthesize storyNavigationController;
@synthesize storyTitlesYCoordinate;
@synthesize storyTitlesOnLeft;
@ -166,7 +169,12 @@
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
self.rotatingToOrientation = toInterfaceOrientation;
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
self.rotatingToOrientation = UIDeviceOrientationUnknown;
if (!self.feedDetailIsVisible) {
[self adjustDashboardScreen];
} else {
@ -238,7 +246,8 @@
popoverController = [[UIPopoverController alloc]
initWithContentViewController:appDelegate.feedsMenuViewController];
[popoverController setDelegate:self];
[popoverController setPopoverContentSize:CGSizeMake(200, 76)];
int menuCount = [appDelegate.feedsMenuViewController.menuOptions count];
[popoverController setPopoverContentSize:CGSizeMake(200, 38 * menuCount)];
[popoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
@ -567,7 +576,7 @@
// CASE: story titles on bottom
self.dashboardViewController.view.frame = CGRectMake(NB_DEFAULT_MASTER_WIDTH + 1, 0, vb.size.width - NB_DEFAULT_MASTER_WIDTH - 1, vb.size.height);
self.masterNavigationController.view.frame = CGRectMake(-NB_DEFAULT_MASTER_WIDTH, 0, NB_DEFAULT_MASTER_WIDTH, vb.size.height);
float smallTimeInterval = NB_DEFAULT_SLIDER_INTERVAL_OUT * NB_DEFAULT_MASTER_WIDTH / vb.size.width;
float largeTimeInterval = NB_DEFAULT_SLIDER_INTERVAL_OUT * ( vb.size.width - NB_DEFAULT_MASTER_WIDTH) / vb.size.width;
@ -638,6 +647,9 @@
self.shareNavigationController.view.frame.size.height - 44);
[self.shareNavigationController.view setNeedsDisplay];
[self.shareViewController.commentField becomeFirstResponder];
if (!self.keyboardIsShown)
[self keyboardWillShowOrHide:nil];
}
- (void)transitionFromShareView {
@ -649,7 +661,7 @@
CGRect vb = [self.view bounds];
self.isSharingStory = NO;
if ([self.shareViewController.commentField isFirstResponder]) {
if ([self.shareViewController.commentField isFirstResponder] && self.keyboardIsShown) {
self.isHidingStory = YES; // the flag allows the keyboard animation to also slide down the share view
[self.shareViewController.commentField resignFirstResponder];
} else {
@ -727,13 +739,20 @@
}
-(void)keyboardWillShowOrHide:(NSNotification*)notification {
if ([notification.name isEqualToString:@"UIKeyboardWillShowNotification"] && !self.isSharingStory) {
if (self.rotatingToOrientation != UIDeviceOrientationUnknown) {
return; // don't animate changes in the old orientation
}
if (notification.name == UIKeyboardWillShowNotification) {
self.keyboardIsShown = YES;
} else if (notification.name == UIKeyboardWillHideNotification) {
self.keyboardIsShown = NO;
}
if (self.keyboardIsShown && !self.isSharingStory) {
return;
}
if ([notification.name isEqualToString:@"UIKeyboardWillHideNotification"] && !self.isHidingStory) {
return;
}
NSDictionary *userInfo = notification.userInfo;
NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
@ -741,15 +760,14 @@
CGRect vb = [self.view bounds];
CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect storyNavigationFrame = self.storyNavigationController.view.frame;
self.shareNavigationController.view.frame = CGRectMake(storyNavigationFrame.origin.x,
vb.size.height,
storyNavigationFrame.size.width,
NB_DEFAULT_SHARE_HEIGHT);
CGRect shareViewFrame = self.shareNavigationController.view.frame;
if ([notification.name isEqualToString:@"UIKeyboardWillShowNotification"]) {
if (self.keyboardIsShown) {
if (UIInterfaceOrientationIsPortrait(orientation)) {
storyNavigationFrame.size.height = vb.size.height - NB_DEFAULT_SHARE_HEIGHT - keyboardFrame.size.height + 44;
shareViewFrame.origin.y = vb.size.height - NB_DEFAULT_SHARE_HEIGHT - keyboardFrame.size.height;
@ -768,10 +786,10 @@
}
// CASE: when dismissing the keyboard but not dismissing the share view
if ([notification.name isEqualToString:@"UIKeyboardWillHideNotification"] && !self.isHidingStory) {
if (!self.keyboardIsShown && !self.isHidingStory) {
self.storyNavigationController.view.frame = storyNavigationFrame;
// CASE: when dismissing the keyboard AND dismissing the share view
} else if ([notification.name isEqualToString:@"UIKeyboardWillHideNotification"] && self.isHidingStory) {
} else if (!self.keyboardIsShown && self.isHidingStory) {
if (UIInterfaceOrientationIsPortrait(orientation) && !self.storyTitlesOnLeft) {
self.storyNavigationController.view.frame = CGRectMake(self.storyNavigationController.view.frame.origin.x,
0,
@ -819,7 +837,7 @@
}
} completion:^(BOOL finished) {
if ([notification.name isEqualToString:@"UIKeyboardWillShowNotification"]) {
if (self.keyboardIsShown) {
self.storyNavigationController.view.frame = storyNavigationFrame;
[self.storyPageControl.currentPage scrolltoComment];
[self.storyPageControl resizeScrollView];

View file

@ -270,6 +270,7 @@
- (void)openTrainStory:(id)sender;
- (void)loadFeedDetailView;
- (void)loadTryFeedDetailView:(NSString *)feedId withStory:(NSString *)contentId isSocial:(BOOL)social withUser:(NSDictionary *)user showFindingStory:(BOOL)showHUD;
- (void)loadStarredDetailViewWithStory:(NSString *)contentId showFindingStory:(BOOL)showHUD;
- (void)loadRiverFeedDetailView;
- (void)loadStoryDetailView;
- (void)adjustStoryDetailWebView;

View file

@ -676,7 +676,43 @@
[self loadFeedDetailView];
if (showHUD) {
[self.storyPageControl showShareHUD:@"Finding story..."];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.storyPageControl showShareHUD:@"Finding story..."];
} else {
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.feedDetailViewController.view animated:YES];
HUD.labelText = @"Finding story...";
}
}
}
- (void)loadStarredDetailViewWithStory:(NSString *)contentId
showFindingStory:(BOOL)showHUD {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[self.navigationController popToRootViewControllerAnimated:NO];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
if (self.feedsViewController.popoverController) {
[self.feedsViewController.popoverController dismissPopoverAnimated:NO];
}
}
self.isSocialRiverView = NO;
self.isRiverView = YES;
self.inFindingStoryMode = YES;
self.isSocialView = NO;
self.tryFeedStoryId = contentId;
self.activeFeed = nil;
self.activeFolder = @"saved_stories";
[self loadRiverFeedDetailView];
if (showHUD) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.storyPageControl showShareHUD:@"Finding story..."];
} else {
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.feedDetailViewController.view animated:YES];
HUD.labelText = @"Finding story...";
}
}
}
@ -968,6 +1004,7 @@
navController.navigationItem.hidesBackButton = YES;
}
[MBProgressHUD hideHUDForView:self.storyPageControl.view animated:YES];
}
- (void)navigationController:(UINavigationController *)navController

View file

@ -31,6 +31,7 @@
#import "FMDatabaseAdditions.h"
#import "IASKAppSettingsViewController.h"
#import "IASKSettingsReader.h"
#import "UIImageView+AFNetworking.h"
#define kPhoneTableViewRowHeight 31;
#define kTableViewRowHeight 31;
@ -550,18 +551,23 @@ static const CGFloat kFolderTitleHeight = 28;
// adding user avatar to left
NSString *url = [NSString stringWithFormat:@"%@", [[results objectForKey:@"social_profile"] objectForKey:@"photo_url"]];
NSURL * imageURL = [NSURL URLWithString:url];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * userAvatarImage = [UIImage imageWithData:imageData];
userAvatarImage = [Utilities roundCorneredImage:userAvatarImage radius:6];
UIButton *userAvatarButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
userAvatarButton.bounds = CGRectMake(0, 0, 32, 32);
userAvatarButton.frame = CGRectMake(0, 0, 32, 32);
[userAvatarButton addTarget:self action:@selector(showUserProfile) forControlEvents:UIControlEventTouchUpInside];
[userAvatarButton setImage:userAvatarImage forState:UIControlStateNormal];
UIBarButtonItem *userInfoBarButton = [[UIBarButtonItem alloc]
initWithCustomView:userAvatarButton];
NSMutableURLRequest *avatarRequest = [NSMutableURLRequest requestWithURL:imageURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
[avatarRequest setHTTPShouldHandleCookies:NO];
[avatarRequest setHTTPShouldUsePipelining:YES];
UIImageView *avatarImageView = [[UIImageView alloc] initWithFrame:userAvatarButton.frame];
[avatarImageView setImageWithURLRequest:avatarRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
image = [Utilities roundCorneredImage:image radius:3];
[userAvatarButton setImage:image forState:UIControlStateNormal];
} failure:nil];
self.navigationItem.leftBarButtonItem = userInfoBarButton;
[self setUserAvatarLayout:orientation];

View file

@ -296,7 +296,7 @@
}
- (IBAction)doOpenActionSheet:(id)sender {
// NSURL *url = [NSURL URLWithString:appDele\0mg ate.activeOriginalStoryURL];
// NSURL *url = [NSURL URLWithString:appDelegate.activeOriginalStoryURL];
NSURL *url = [NSURL URLWithString:self.pageUrl.text];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

View file

@ -7,7 +7,6 @@
//
#import "SmallActivityCell.h"
#import "NSAttributedString+Attributes.h"
#import "UIImageView+AFNetworking.h"
#import <QuartzCore/QuartzCore.h>
@ -24,9 +23,8 @@
self.faviconView = favicon;
[self.contentView addSubview:favicon];
OHAttributedLabel *activity = [[OHAttributedLabel alloc] initWithFrame:CGRectZero];
UILabel *activity = [[UILabel alloc] initWithFrame:CGRectZero];
activity.backgroundColor = [UIColor whiteColor];
activity.automaticallyAddLinksForType = NO;
self.activityLabel = activity;
[self.contentView addSubview:activity];
@ -62,6 +60,7 @@
self.activityLabel.backgroundColor = UIColorFromRGB(0xf6f6f6);
}
self.activityLabel.backgroundColor = [UIColor clearColor];
[self.activityLabel sizeToFit];
}
@end

View file

@ -7,7 +7,6 @@
//
#import "SmallInteractionCell.h"
#import "NSAttributedString+Attributes.h"
#import "UIImageView+AFNetworking.h"
#import <QuartzCore/QuartzCore.h>
@ -24,9 +23,8 @@
self.avatarView = favicon;
[self.contentView addSubview:favicon];
OHAttributedLabel *interaction = [[OHAttributedLabel alloc] initWithFrame:CGRectZero];
UILabel *interaction = [[UILabel alloc] initWithFrame:CGRectZero];
interaction.backgroundColor = [UIColor whiteColor];
interaction.automaticallyAddLinksForType = NO;
self.interactionLabel = interaction;
[self.contentView addSubview:interaction];
@ -62,6 +60,7 @@
self.interactionLabel.backgroundColor = UIColorFromRGB(0xf6f6f6);
}
self.interactionLabel.backgroundColor = [UIColor clearColor];
[self.interactionLabel sizeToFit];
}
@end

View file

@ -33,12 +33,14 @@
@property (nonatomic) IBOutlet UIWebView *webView;
@property (nonatomic) IBOutlet UIView *feedTitleGradient;
@property (nonatomic) IBOutlet UILabel *noStorySelectedLabel;
@property (nonatomic) IBOutlet UIImageView *noStorySelectedImage;
@property (nonatomic, assign) BOOL pullingScrollview;
@property (nonatomic, assign) BOOL inTextView;
@property NSInteger pageIndex;
@property (nonatomic) MBProgressHUD *storyHUD;
- (void)initStory;
- (void)hideNoStoryMessage;
- (void)drawStory;
- (void)drawStory:(BOOL)force withOrientation:(UIInterfaceOrientation)orientation;
- (void)showStory;

View file

@ -33,6 +33,7 @@
@synthesize webView;
@synthesize feedTitleGradient;
@synthesize noStorySelectedLabel;
@synthesize noStorySelectedImage;
@synthesize pullingScrollview;
@synthesize pageIndex;
@synthesize storyHUD;
@ -75,6 +76,7 @@
- (void)viewDidUnload {
[self setInnerView:nil];
[self setNoStorySelectedLabel:nil];
[super viewDidUnload];
}
@ -98,17 +100,19 @@
appDelegate.inStoryDetail = YES;
self.noStorySelectedLabel.hidden = YES;
self.noStorySelectedImage.hidden = YES;
appDelegate.shareViewController.commentField.text = nil;
self.webView.hidden = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.masterContainerViewController transitionFromShareView];
}
[appDelegate hideShareView:YES];
[appDelegate resetShareComments];
}
- (void)hideNoStoryMessage {
self.noStorySelectedLabel.hidden = YES;
self.noStorySelectedImage.hidden = YES;
}
- (void)drawStory {
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
[self drawStory:NO withOrientation:orientation];
@ -282,6 +286,7 @@
self.activeStoryId = nil;
self.webView.hidden = YES;
self.noStorySelectedLabel.hidden = NO;
self.noStorySelectedImage.hidden = NO;
}
#pragma mark -

View file

@ -245,7 +245,6 @@
NSLog(@"Rotate: %f,%f",self.view.frame.size.width,self.view.frame.size.height);
}
[self refreshPages];
[self layoutForInterfaceOrientation:toInterfaceOrientation];
}
@ -253,7 +252,9 @@
if (interfaceOrientation != _orientation) {
_orientation = interfaceOrientation;
[self refreshPages];
previousPage.view.hidden = YES;
if (currentPage.pageIndex == 0) {
previousPage.view.hidden = YES;
}
}
}
@ -521,7 +522,10 @@
frame.origin.y = 0;
self.scrollingToPage = pageIndex;
[self.currentPage hideNoStoryMessage];
[self.nextPage hideNoStoryMessage];
[self.previousPage hideNoStoryMessage];
// Check if already on the selected page
if (self.scrollView.contentOffset.x == frame.origin.x) {
[self applyNewIndex:pageIndex pageController:currentPage];

View file

@ -67,13 +67,12 @@
applicationActivities:appActivities];
[shareSheet setValue:[appDelegate.activeStory objectForKey:@"story_title"] forKey:@"subject"];
[shareSheet setCompletionHandler:^(NSString *activityType, BOOL completed) {
if (completed) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
// [[NSNotificationCenter defaultCenter] addObserver:self
// selector:@selector(keyboardDidHide:)
// name:UIKeyboardDidHideNotification
// object:nil];
NSString *_completedString;
if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {

View file

@ -198,7 +198,7 @@
SmallActivityCell *activityCell = [[SmallActivityCell alloc] init];
int height = [activityCell setActivity:[self.activitiesArray objectAtIndex:(indexPath.row)]
withUserProfile:self.userProfile
withWidth:width] + 20;
withWidth:width];
return height;
}
}

View file

@ -1,80 +0,0 @@
/***********************************************************************************
*
* Copyright (c) 2010 Olivier Halligon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
***********************************************************************************
*
* Created by Olivier Halligon (AliSoftware) on 20 Jul. 2010.
*
* Any comment or suggestion welcome. Please contact me before using this class in
* your projects. Referencing this project in your AboutBox/Credits is appreciated.
*
***********************************************************************************/
#import <Foundation/Foundation.h>
#import <CoreText/CoreText.h>
#import <UIKit/UIKit.h>
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: NSAttributedString Additions
/////////////////////////////////////////////////////////////////////////////
@interface NSAttributedString (OHCommodityConstructors)
+(id)attributedStringWithString:(NSString*)string;
+(id)attributedStringWithAttributedString:(NSAttributedString*)attrStr;
//! Commodity method that call the following sizeConstrainedToSize:fitRange: method with NULL for the fitRange parameter
-(CGSize)sizeConstrainedToSize:(CGSize)maxSize;
//! if fitRange is not NULL, on return it will contain the used range that actually fits the constrained size.
//! Note: Use CGFLOAT_MAX for the CGSize's height if you don't want a constraint for the height.
-(CGSize)sizeConstrainedToSize:(CGSize)maxSize fitRange:(NSRange*)fitRange;
@end
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: NSMutableAttributedString Additions
/////////////////////////////////////////////////////////////////////////////
@interface NSMutableAttributedString (OHCommodityStyleModifiers)
-(void)setFont:(UIFont*)font;
-(void)setFont:(UIFont*)font range:(NSRange)range;
-(void)setFontName:(NSString*)fontName size:(CGFloat)size;
-(void)setFontName:(NSString*)fontName size:(CGFloat)size range:(NSRange)range;
-(void)setFontFamily:(NSString*)fontFamily size:(CGFloat)size bold:(BOOL)isBold italic:(BOOL)isItalic range:(NSRange)range;
-(void)setTextColor:(UIColor*)color;
-(void)setTextColor:(UIColor*)color range:(NSRange)range;
-(void)setTextIsUnderlined:(BOOL)underlined;
-(void)setTextIsUnderlined:(BOOL)underlined range:(NSRange)range;
-(void)setTextUnderlineStyle:(int32_t)style range:(NSRange)range; //!< style is a combination of CTUnderlineStyle & CTUnderlineStyleModifiers
-(void)setTextBold:(BOOL)isBold range:(NSRange)range;
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode;
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode lineHeight:(CGFloat)lineHeight;
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode range:(NSRange)range;
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode range:(NSRange)range lineHeight:(CGFloat)lineHeight;
@end

View file

@ -1,185 +0,0 @@
/***********************************************************************************
*
* Copyright (c) 2010 Olivier Halligon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
***********************************************************************************
*
* Created by Olivier Halligon (AliSoftware) on 20 Jul. 2010.
*
* Any comment or suggestion welcome. Please contact me before using this class in
* your projects. Referencing this project in your AboutBox/Credits is appreciated.
*
***********************************************************************************/
#import "NSAttributedString+Attributes.h"
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: NS(Mutable)AttributedString Additions
/////////////////////////////////////////////////////////////////////////////
@implementation NSAttributedString (OHCommodityConstructors)
+(id)attributedStringWithString:(NSString*)string {
return string ? [[[self alloc] initWithString:string] autorelease] : nil;
}
+(id)attributedStringWithAttributedString:(NSAttributedString*)attrStr {
return attrStr ? [[[self alloc] initWithAttributedString:attrStr] autorelease] : nil;
}
-(CGSize)sizeConstrainedToSize:(CGSize)maxSize {
return [self sizeConstrainedToSize:maxSize fitRange:NULL];
}
-(CGSize)sizeConstrainedToSize:(CGSize)maxSize fitRange:(NSRange*)fitRange {
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self);
CFRange fitCFRange = CFRangeMake(0,0);
CGSize sz = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0,0),NULL,maxSize,&fitCFRange);
if (framesetter) CFRelease(framesetter);
if (fitRange) *fitRange = NSMakeRange(fitCFRange.location, fitCFRange.length);
return CGSizeMake( floorf(sz.width+1) , floorf(sz.height+1) ); // take 1pt of margin for security
}
@end
@implementation NSMutableAttributedString (OHCommodityStyleModifiers)
-(void)setFont:(UIFont*)font {
[self setFontName:font.fontName size:font.pointSize];
}
-(void)setFont:(UIFont*)font range:(NSRange)range {
[self setFontName:font.fontName size:font.pointSize range:range];
}
-(void)setFontName:(NSString*)fontName size:(CGFloat)size {
[self setFontName:fontName size:size range:NSMakeRange(0,[self length])];
}
-(void)setFontName:(NSString*)fontName size:(CGFloat)size range:(NSRange)range {
// kCTFontAttributeName
CTFontRef aFont = CTFontCreateWithName((CFStringRef)fontName, size, NULL);
if (!aFont) return;
[self removeAttribute:(NSString*)kCTFontAttributeName range:range]; // Work around for Apple leak
[self addAttribute:(NSString*)kCTFontAttributeName value:(id)aFont range:range];
CFRelease(aFont);
}
-(void)setFontFamily:(NSString*)fontFamily size:(CGFloat)size bold:(BOOL)isBold italic:(BOOL)isItalic range:(NSRange)range {
// kCTFontFamilyNameAttribute + kCTFontTraitsAttribute
CTFontSymbolicTraits symTrait = (isBold?kCTFontBoldTrait:0) | (isItalic?kCTFontItalicTrait:0);
NSDictionary* trait = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:symTrait] forKey:(NSString*)kCTFontSymbolicTrait];
NSDictionary* attr = [NSDictionary dictionaryWithObjectsAndKeys:
fontFamily,kCTFontFamilyNameAttribute,
trait,kCTFontTraitsAttribute,nil];
CTFontDescriptorRef desc = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attr);
if (!desc) return;
CTFontRef aFont = CTFontCreateWithFontDescriptor(desc, size, NULL);
CFRelease(desc);
if (!aFont) return;
[self removeAttribute:(NSString*)kCTFontAttributeName range:range]; // Work around for Apple leak
[self addAttribute:(NSString*)kCTFontAttributeName value:(id)aFont range:range];
CFRelease(aFont);
}
-(void)setTextColor:(UIColor*)color {
[self setTextColor:color range:NSMakeRange(0,[self length])];
}
-(void)setTextColor:(UIColor*)color range:(NSRange)range {
// kCTForegroundColorAttributeName
[self removeAttribute:(NSString*)kCTForegroundColorAttributeName range:range]; // Work around for Apple leak
[self addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)color.CGColor range:range];
}
-(void)setTextIsUnderlined:(BOOL)underlined {
[self setTextIsUnderlined:underlined range:NSMakeRange(0,[self length])];
}
-(void)setTextIsUnderlined:(BOOL)underlined range:(NSRange)range {
int32_t style = underlined ? (kCTUnderlineStyleSingle|kCTUnderlinePatternSolid) : kCTUnderlineStyleNone;
[self setTextUnderlineStyle:style range:range];
}
-(void)setTextUnderlineStyle:(int32_t)style range:(NSRange)range {
[self removeAttribute:(NSString*)kCTUnderlineStyleAttributeName range:range]; // Work around for Apple leak
[self addAttribute:(NSString*)kCTUnderlineStyleAttributeName value:[NSNumber numberWithInt:style] range:range];
}
-(void)setTextBold:(BOOL)isBold range:(NSRange)range {
NSUInteger startPoint = range.location;
NSRange effectiveRange;
do {
// Get font at startPoint
CTFontRef currentFont = (CTFontRef)[self attribute:(NSString*)kCTFontAttributeName atIndex:startPoint effectiveRange:&effectiveRange];
// The range for which this font is effective
NSRange fontRange = NSIntersectionRange(range, effectiveRange);
// Create bold/unbold font variant for this font and apply
CTFontRef newFont = CTFontCreateCopyWithSymbolicTraits(currentFont, 0.0, NULL, (isBold?kCTFontBoldTrait:0), kCTFontBoldTrait);
if (newFont) {
[self removeAttribute:(NSString*)kCTFontAttributeName range:fontRange]; // Work around for Apple leak
[self addAttribute:(NSString*)kCTFontAttributeName value:(id)newFont range:fontRange];
CFRelease(newFont);
} else {
NSString* fontName = [(NSString*)CTFontCopyFullName(currentFont) autorelease];
NSLog(@"[OHAttributedLabel] Warning: can't find a bold font variant for font %@. Try another font family (like Helvetica) instead.",fontName);
}
////[self removeAttribute:(NSString*)kCTFontWeightTrait range:fontRange]; // Work around for Apple leak
////[self addAttribute:(NSString*)kCTFontWeightTrait value:(id)[NSNumber numberWithInt:1.0f] range:fontRange];
// If the fontRange was not covering the whole range, continue with next run
startPoint = NSMaxRange(effectiveRange);
} while(startPoint<NSMaxRange(range));
}
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode {
[self setTextAlignment:alignment lineBreakMode:lineBreakMode range:NSMakeRange(0,[self length])];
}
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode lineHeight:(CGFloat)lineHeight{
[self setTextAlignment:alignment lineBreakMode:lineBreakMode range:NSMakeRange(0,[self length]) lineHeight:lineHeight];
}
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode range:(NSRange)range {
// kCTParagraphStyleAttributeName > kCTParagraphStyleSpecifierAlignment
CTParagraphStyleSetting paraStyles[2] = {
{.spec = kCTParagraphStyleSpecifierAlignment, .valueSize = sizeof(CTTextAlignment), .value = (const void*)&alignment},
{.spec = kCTParagraphStyleSpecifierLineBreakMode, .valueSize = sizeof(CTLineBreakMode), .value = (const void*)&lineBreakMode},
};
CTParagraphStyleRef aStyle = CTParagraphStyleCreate(paraStyles, 2);
[self removeAttribute:(NSString*)kCTParagraphStyleAttributeName range:range]; // Work around for Apple leak
[self addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)aStyle range:range];
CFRelease(aStyle);
}
-(void)setTextAlignment:(CTTextAlignment)alignment lineBreakMode:(CTLineBreakMode)lineBreakMode range:(NSRange)range lineHeight:(CGFloat)lineHeight{
CTParagraphStyleSetting paraStyles[3] = {
{.spec = kCTParagraphStyleSpecifierAlignment, .valueSize = sizeof(CTTextAlignment), .value = (const void*)&alignment},
{.spec = kCTParagraphStyleSpecifierLineBreakMode, .valueSize = sizeof(CTLineBreakMode), .value = (const void*)&lineBreakMode},
{.spec = kCTParagraphStyleSpecifierLineSpacing, .valueSize = sizeof(lineHeight),.value =(const void*)&lineHeight},
};
CTParagraphStyleRef aStyle = CTParagraphStyleCreate(paraStyles, 3);
[self removeAttribute:(NSString*)kCTParagraphStyleAttributeName range:range]; // Work around for Apple leak
[self addAttribute:(NSString*)kCTParagraphStyleAttributeName value:(id)aStyle range:range];
CFRelease(aStyle);
}
@end

View file

@ -49,7 +49,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.4.5</string>
<string>3.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@ -78,7 +78,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>2.4.5</string>
<string>3.0</string>
<key>FacebookAppID</key>
<string>230426707030569</string>
<key>LSRequiresIPhoneOS</key>

Binary file not shown.

View file

@ -35,7 +35,7 @@
<key>bundle-identifier</key>
<string>com.newsblur.NewsBlur</string>
<key>bundle-version</key>
<string>2.4.5</string>
<string>2.4.6</string>
<key>kind</key>
<string>software</string>
<key>title</key>

View file

@ -163,8 +163,6 @@
43E8382315BC73EB000553BE /* FirstTimeUserAddSitesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 43E8381D15BC73EB000553BE /* FirstTimeUserAddSitesViewController.xib */; };
43F44B1C159D8DBC00F48F8A /* FeedTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 43F44B1B159D8D7200F48F8A /* FeedTableCell.m */; };
43F6A79D15B0CDC60092EE91 /* ActivityCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 43F6A79C15B0CDC60092EE91 /* ActivityCell.m */; };
43F6A7A615B0E1A40092EE91 /* NSAttributedString+Attributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 43F6A7A315B0E1A40092EE91 /* NSAttributedString+Attributes.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
43F6A7A715B0E1A40092EE91 /* OHAttributedLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 43F6A7A515B0E1A40092EE91 /* OHAttributedLabel.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
43F6A7A915B0E1ED0092EE91 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43F6A7A815B0E1ED0092EE91 /* CoreText.framework */; };
78095E34128EF30C00230C8E /* ASIAuthenticationDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 78095E25128EF30C00230C8E /* ASIAuthenticationDialog.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
78095E35128EF30D00230C8E /* ASIDownloadCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 78095E28128EF30C00230C8E /* ASIDownloadCache.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
@ -428,6 +426,8 @@
FFDE35EA162799B90034BFDE /* FeedDetailMenuViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFDE35E9162799B90034BFDE /* FeedDetailMenuViewController.m */; };
FFDE35ED1627A1C40034BFDE /* FeedDetailMenuViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = FFDE35EC1627A1C40034BFDE /* FeedDetailMenuViewController.xib */; };
FFE5322F144C8AC300ACFDE0 /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = FFE5322E144C8AC300ACFDE0 /* Utilities.m */; };
FFE816AB17E280BD008AF4B0 /* ftux_tree.png in Resources */ = {isa = PBXBuildFile; fileRef = FFE816AA17E280BD008AF4B0 /* ftux_tree.png */; };
FFE816AD17E29D71008AF4B0 /* big_world_white.png in Resources */ = {isa = PBXBuildFile; fileRef = FFE816AC17E29D71008AF4B0 /* big_world_white.png */; };
FFECD019172B105800D45A62 /* UIActivitySafari.png in Resources */ = {isa = PBXBuildFile; fileRef = FFECD017172B105800D45A62 /* UIActivitySafari.png */; };
FFECD01A172B105800D45A62 /* UIActivitySafari@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFECD018172B105800D45A62 /* UIActivitySafari@2x.png */; };
FFF1E4B9177504CA00BF59D3 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFF1E49B177504CA00BF59D3 /* IASKAppSettingsViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
@ -660,10 +660,6 @@
43F44B1B159D8D7200F48F8A /* FeedTableCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FeedTableCell.m; sourceTree = "<group>"; };
43F6A79B15B0CDC60092EE91 /* ActivityCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActivityCell.h; sourceTree = "<group>"; };
43F6A79C15B0CDC60092EE91 /* ActivityCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActivityCell.m; sourceTree = "<group>"; };
43F6A7A215B0E1A40092EE91 /* NSAttributedString+Attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSAttributedString+Attributes.h"; sourceTree = "<group>"; };
43F6A7A315B0E1A40092EE91 /* NSAttributedString+Attributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSAttributedString+Attributes.m"; sourceTree = "<group>"; };
43F6A7A415B0E1A40092EE91 /* OHAttributedLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OHAttributedLabel.h; sourceTree = "<group>"; };
43F6A7A515B0E1A40092EE91 /* OHAttributedLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OHAttributedLabel.m; sourceTree = "<group>"; };
43F6A7A815B0E1ED0092EE91 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
78095E24128EF30C00230C8E /* ASIAuthenticationDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIAuthenticationDialog.h; sourceTree = "<group>"; };
78095E25128EF30C00230C8E /* ASIAuthenticationDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIAuthenticationDialog.m; sourceTree = "<group>"; };
@ -1035,6 +1031,8 @@
FFDE35EC1627A1C40034BFDE /* FeedDetailMenuViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FeedDetailMenuViewController.xib; sourceTree = "<group>"; };
FFE5322D144C8AC300ACFDE0 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
FFE5322E144C8AC300ACFDE0 /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = "<group>"; };
FFE816AA17E280BD008AF4B0 /* ftux_tree.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ftux_tree.png; sourceTree = "<group>"; };
FFE816AC17E29D71008AF4B0 /* big_world_white.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = big_world_white.png; sourceTree = "<group>"; };
FFECD017172B105800D45A62 /* UIActivitySafari.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = UIActivitySafari.png; sourceTree = "<group>"; };
FFECD018172B105800D45A62 /* UIActivitySafari@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "UIActivitySafari@2x.png"; sourceTree = "<group>"; };
FFF1E49A177504CA00BF59D3 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = "<group>"; };
@ -1154,10 +1152,6 @@
FF22FE5316E53ADC0046165A /* Underscore */,
43A4BABE15C8663600F3B8D4 /* Popover */,
43A3912E15B73A7B0074B212 /* AFNetworking */,
43F6A7A215B0E1A40092EE91 /* NSAttributedString+Attributes.h */,
43F6A7A315B0E1A40092EE91 /* NSAttributedString+Attributes.m */,
43F6A7A415B0E1A40092EE91 /* OHAttributedLabel.h */,
43F6A7A515B0E1A40092EE91 /* OHAttributedLabel.m */,
FFFC60821716578E00DC22E2 /* THCircularProgressView.h */,
FFFC60831716578E00DC22E2 /* THCircularProgressView.m */,
43A4C3E615B0099B008787B5 /* NewsBlur_Prefix.pch */,
@ -1340,6 +1334,8 @@
431B857615A132B600DCE497 /* Images */ = {
isa = PBXGroup;
children = (
FFE816AC17E29D71008AF4B0 /* big_world_white.png */,
FFE816AA17E280BD008AF4B0 /* ftux_tree.png */,
FF855B541794A53A0098D48A /* checkmark.png */,
FF855B551794A53A0098D48A /* checkmark@2x.png */,
FFF1E4C917750D2C00BF59D3 /* menu_icn_preferences.png */,
@ -2459,6 +2455,8 @@
FF5D4018179A00B900349659 /* traverse_send@2x.png in Resources */,
FF5D401B179A03E700349659 /* traverse_previous_off.png in Resources */,
FF5D401C179A03E700349659 /* traverse_previous_off@2x.png in Resources */,
FFE816AB17E280BD008AF4B0 /* ftux_tree.png in Resources */,
FFE816AD17E29D71008AF4B0 /* big_world_white.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2520,8 +2518,6 @@
43A4C3E415B00966008787B5 /* TransparentToolbar.m in Sources */,
43A4C3E515B00966008787B5 /* UIView+TKCategory.m in Sources */,
43F6A79D15B0CDC60092EE91 /* ActivityCell.m in Sources */,
43F6A7A615B0E1A40092EE91 /* NSAttributedString+Attributes.m in Sources */,
43F6A7A715B0E1A40092EE91 /* OHAttributedLabel.m in Sources */,
43ABBCAA15B53A1400EA3111 /* InteractionCell.m in Sources */,
43A3914415B73A7B0074B212 /* AFHTTPClient.m in Sources */,
43A3914515B73A7B0074B212 /* AFHTTPRequestOperation.m in Sources */,
@ -2652,8 +2648,8 @@
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = Entitlements.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution: NewsBlur, Inc.";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: NewsBlur, Inc.";
CODE_SIGN_IDENTITY = "iPhone Distribution: NewsBlur, Inc. (HR7P97SD72)";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: NewsBlur, Inc. (HR7P97SD72)";
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@ -2676,8 +2672,8 @@
"-all_load",
);
PRODUCT_NAME = NewsBlur;
PROVISIONING_PROFILE = "A0156932-124B-4F8E-8B93-EE6598D778F0";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "A0156932-124B-4F8E-8B93-EE6598D778F0";
PROVISIONING_PROFILE = "954389F4-8E6B-4312-9C44-7DCD5EAD40A5";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "954389F4-8E6B-4312-9C44-7DCD5EAD40A5";
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = armv7;
"WARNING_CFLAGS[arch=*]" = "-Wall";
@ -2691,8 +2687,8 @@
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = Entitlements.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution: NewsBlur, Inc.";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: NewsBlur, Inc.";
CODE_SIGN_IDENTITY = "iPhone Distribution: NewsBlur, Inc. (HR7P97SD72)";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: NewsBlur, Inc. (HR7P97SD72)";
COPY_PHASE_STRIP = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = NewsBlur_Prefix.pch;
@ -2712,8 +2708,8 @@
"-all_load",
);
PRODUCT_NAME = NewsBlur;
PROVISIONING_PROFILE = "A0156932-124B-4F8E-8B93-EE6598D778F0";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "A0156932-124B-4F8E-8B93-EE6598D778F0";
PROVISIONING_PROFILE = "954389F4-8E6B-4312-9C44-7DCD5EAD40A5";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "954389F4-8E6B-4312-9C44-7DCD5EAD40A5";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VALID_ARCHS = armv7;
@ -2724,8 +2720,8 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_IDENTITY = "iPhone Distribution: NewsBlur, Inc.";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: NewsBlur, Inc.";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@ -2734,8 +2730,8 @@
HEADER_SEARCH_PATHS = "$(BUILT_PRODUCTS_DIR)/**";
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
OTHER_LDFLAGS = "-ObjC";
PROVISIONING_PROFILE = "A0156932-124B-4F8E-8B93-EE6598D778F0";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "A0156932-124B-4F8E-8B93-EE6598D778F0";
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphoneos;
STRIP_INSTALLED_PRODUCT = NO;
@ -2747,8 +2743,8 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_IDENTITY = "iPhone Distribution: NewsBlur, Inc.";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: NewsBlur, Inc.";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@ -2758,8 +2754,8 @@
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
OTHER_LDFLAGS = "-ObjC";
PROVISIONING_PROFILE = "A0156932-124B-4F8E-8B93-EE6598D778F0";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "A0156932-124B-4F8E-8B93-EE6598D778F0";
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
SDKROOT = iphoneos;
STRIP_INSTALLED_PRODUCT = NO;
VALID_ARCHS = armv7;

View file

@ -1,85 +0,0 @@
/***********************************************************************************
*
* Copyright (c) 2010 Olivier Halligon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
***********************************************************************************
*
* Created by Olivier Halligon (AliSoftware) on 20 Jul. 2010.
*
* Any comment or suggestion welcome. Please contact me before using this class in
* your projects. Referencing this project in your AboutBox/Credits is appreciated.
*
***********************************************************************************/
#import <UIKit/UIKit.h>
#import <CoreText/CoreText.h>
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: Utility Functions
/////////////////////////////////////////////////////////////////////////////
CTTextAlignment CTTextAlignmentFromUITextAlignment(UITextAlignment alignment);
CTLineBreakMode CTLineBreakModeFromUILineBreakMode(UILineBreakMode lineBreakMode);
/////////////////////////////////////////////////////////////////////////////
@class OHAttributedLabel;
@protocol OHAttributedLabelDelegate <NSObject>
@optional
-(BOOL)attributedLabel:(OHAttributedLabel*)attributedLabel shouldFollowLink:(NSTextCheckingResult*)linkInfo;
-(UIColor*)colorForLink:(NSTextCheckingResult*)linkInfo underlineStyle:(int32_t*)underlineStyle; //!< Combination of CTUnderlineStyle and CTUnderlineStyleModifiers
@end
#define UITextAlignmentJustify ((UITextAlignment)kCTJustifiedTextAlignment)
/////////////////////////////////////////////////////////////////////////////
@interface OHAttributedLabel : UILabel {
NSMutableAttributedString* _attributedText; //!< Internally mutable, but externally immutable copy access only
CTFrameRef textFrame;
CGRect drawingRect;
NSMutableArray* customLinks;
NSTextCheckingResult* activeLink;
CGPoint touchStartPoint;
}
/* Attributed String accessors */
@property(nonatomic, copy) NSAttributedString* attributedText; //!< Use this instead of the "text" property inherited from UILabel to set and get text
-(void)resetAttributedText; //!< rebuild the attributedString based on UILabel's text/font/color/alignment/... properties
/* Links configuration */
@property(nonatomic, assign) NSTextCheckingTypes automaticallyAddLinksForType; //!< Defaults to NSTextCheckingTypeLink, + NSTextCheckingTypePhoneNumber if "tel:" scheme supported
@property(nonatomic, retain) UIColor* linkColor; //!< Defaults to [UIColor blueColor]. See also OHAttributedLabelDelegate
@property(nonatomic, retain) UIColor* highlightedLinkColor; //[UIColor colorWithWhite:0.2 alpha:0.5]
@property(nonatomic, assign) BOOL underlineLinks; //!< Defaults to YES. See also OHAttributedLabelDelegate
-(void)addCustomLink:(NSURL*)linkUrl inRange:(NSRange)range;
-(void)removeAllCustomLinks;
@property(nonatomic, assign) BOOL onlyCatchTouchesOnLinks; //!< If YES, pointInside will only return YES if the touch is on a link. If NO, pointInside will always return YES (Defaults to NO)
@property(nonatomic, assign) IBOutlet id<OHAttributedLabelDelegate> delegate;
@property(nonatomic, assign) BOOL centerVertically;
@property(nonatomic, assign) BOOL extendBottomToFit; //!< Allows to draw text past the bottom of the view if need. May help in rare cases (like using Emoji)
@end

View file

@ -1,659 +0,0 @@
/***********************************************************************************
*
* Copyright (c) 2010 Olivier Halligon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
***********************************************************************************
*
* Created by Olivier Halligon (AliSoftware) on 20 Jul. 2010.
*
* Any comment or suggestion welcome. Please contact me before using this class in
* your projects. Referencing this project in your AboutBox/Credits is appreciated.
*
***********************************************************************************/
#import "OHAttributedLabel.h"
#import "NSAttributedString+Attributes.h"
#define OHAttributedLabel_WarnAboutKnownIssues 1
/////////////////////////////////////////////////////////////////////////////
// MARK: Private Utility methods
CGPoint CGPointFlipped(CGPoint point, CGRect bounds);
CGRect CGRectFlipped(CGRect rect, CGRect bounds);
NSRange NSRangeFromCFRange(CFRange range);
CGRect CTLineGetTypographicBoundsAsRect(CTLineRef line, CGPoint lineOrigin);
CGRect CTRunGetTypographicBoundsAsRect(CTRunRef run, CTLineRef line, CGPoint lineOrigin);
BOOL CTLineContainsCharactersFromStringRange(CTLineRef line, NSRange range);
BOOL CTRunContainsCharactersFromStringRange(CTRunRef run, NSRange range);
/////////////////////////////////////////////////////////////////////////////
// MARK: -
/////////////////////////////////////////////////////////////////////////////
CTTextAlignment CTTextAlignmentFromUITextAlignment(UITextAlignment alignment) {
switch (alignment) {
case NSTextAlignmentLeft: return kCTLeftTextAlignment;
case UITextAlignmentCenter: return kCTCenterTextAlignment;
case UITextAlignmentRight: return kCTRightTextAlignment;
case UITextAlignmentJustify: return kCTJustifiedTextAlignment; /* special OOB value if we decide to use it even if it's not really standard... */
default: return kCTNaturalTextAlignment;
}
}
CTLineBreakMode CTLineBreakModeFromUILineBreakMode(UILineBreakMode lineBreakMode) {
switch (lineBreakMode) {
case UILineBreakModeWordWrap: return kCTLineBreakByWordWrapping;
case UILineBreakModeCharacterWrap: return kCTLineBreakByCharWrapping;
case UILineBreakModeClip: return kCTLineBreakByClipping;
case UILineBreakModeHeadTruncation: return kCTLineBreakByTruncatingHead;
case NSLineBreakByTruncatingTail: return kCTLineBreakByTruncatingTail;
case UILineBreakModeMiddleTruncation: return kCTLineBreakByTruncatingMiddle;
default: return 0;
}
}
// Don't use this method for origins. Origins always depend on the height of the rect.
CGPoint CGPointFlipped(CGPoint point, CGRect bounds) {
return CGPointMake(point.x, CGRectGetMaxY(bounds)-point.y);
}
CGRect CGRectFlipped(CGRect rect, CGRect bounds) {
return CGRectMake(CGRectGetMinX(rect),
CGRectGetMaxY(bounds)-CGRectGetMaxY(rect),
CGRectGetWidth(rect),
CGRectGetHeight(rect));
}
NSRange NSRangeFromCFRange(CFRange range) {
return NSMakeRange(range.location, range.length);
}
// Font Metrics: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/FontHandling/Tasks/GettingFontMetrics.html
CGRect CTLineGetTypographicBoundsAsRect(CTLineRef line, CGPoint lineOrigin) {
CGFloat ascent = 0;
CGFloat descent = 0;
CGFloat leading = 0;
CGFloat width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
CGFloat height = ascent + descent /* + leading */;
return CGRectMake(lineOrigin.x,
lineOrigin.y - descent,
width,
height);
}
CGRect CTRunGetTypographicBoundsAsRect(CTRunRef run, CTLineRef line, CGPoint lineOrigin) {
CGFloat ascent = 0;
CGFloat descent = 0;
CGFloat leading = 0;
CGFloat width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, &leading);
CGFloat height = ascent + descent /* + leading */;
CGFloat xOffset = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL);
return CGRectMake(lineOrigin.x + xOffset,
lineOrigin.y - descent,
width,
height);
}
BOOL CTLineContainsCharactersFromStringRange(CTLineRef line, NSRange range) {
NSRange lineRange = NSRangeFromCFRange(CTLineGetStringRange(line));
NSRange intersectedRange = NSIntersectionRange(lineRange, range);
return (intersectedRange.length > 0);
}
BOOL CTRunContainsCharactersFromStringRange(CTRunRef run, NSRange range) {
NSRange runRange = NSRangeFromCFRange(CTRunGetStringRange(run));
NSRange intersectedRange = NSIntersectionRange(runRange, range);
return (intersectedRange.length > 0);
}
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: Private interface
/////////////////////////////////////////////////////////////////////////////
@interface OHAttributedLabel(/* Private */)
-(NSTextCheckingResult*)linkAtCharacterIndex:(CFIndex)idx;
-(NSTextCheckingResult*)linkAtPoint:(CGPoint)pt;
-(NSMutableAttributedString*)attributedTextWithLinks;
-(void)resetTextFrame;
-(void)drawActiveLinkHighlightForRect:(CGRect)rect;
#if OHAttributedLabel_WarnAboutKnownIssues
-(void)warnAboutKnownIssues_CheckLineBreakMode;
-(void)warnAboutKnownIssues_CheckAdjustsFontSizeToFitWidth;
#endif
@end
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: Implementation
/////////////////////////////////////////////////////////////////////////////
@implementation OHAttributedLabel
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: Init/Dealloc
/////////////////////////////////////////////////////////////////////////////
- (void)commonInit
{
customLinks = [[NSMutableArray alloc] init];
self.linkColor = [UIColor blueColor];
self.highlightedLinkColor = [UIColor colorWithWhite:0.4 alpha:0.3];
self.underlineLinks = YES;
self.automaticallyAddLinksForType = NSTextCheckingTypeLink;
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel:0"]]) {
self.automaticallyAddLinksForType |= NSTextCheckingTypePhoneNumber;
}
self.onlyCatchTouchesOnLinks = YES;
self.userInteractionEnabled = YES;
self.contentMode = UIViewContentModeRedraw;
[self resetAttributedText];
}
- (id) initWithFrame:(CGRect)aFrame
{
self = [super initWithFrame:aFrame];
if (self != nil) {
[self commonInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super initWithCoder:decoder];
if (self != nil) {
[self commonInit];
#if OHAttributedLabel_WarnAboutKnownIssues
[self warnAboutKnownIssues_CheckLineBreakMode];
[self warnAboutKnownIssues_CheckAdjustsFontSizeToFitWidth];
#endif
}
return self;
}
-(void)dealloc
{
[_attributedText release];
[self resetTextFrame];
[customLinks release];
self.linkColor = nil;
self.highlightedLinkColor = nil;
[activeLink release];
[super dealloc];
}
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: Links Mgmt
/////////////////////////////////////////////////////////////////////////////
-(void)addCustomLink:(NSURL*)linkUrl inRange:(NSRange)range {
NSTextCheckingResult* link = [NSTextCheckingResult linkCheckingResultWithRange:range URL:linkUrl];
[customLinks addObject:link];
[self setNeedsDisplay];
}
-(void)removeAllCustomLinks {
[customLinks removeAllObjects];
[self setNeedsDisplay];
}
-(NSMutableAttributedString*)attributedTextWithLinks {
NSMutableAttributedString* str = [self.attributedText mutableCopy];
if (!str) return nil;
NSString* plainText = [str string];
if (plainText && (self.automaticallyAddLinksForType > 0)) {
NSError* error = nil;
NSDataDetector* linkDetector = [NSDataDetector dataDetectorWithTypes:self.automaticallyAddLinksForType error:&error];
[linkDetector enumerateMatchesInString:plainText options:0 range:NSMakeRange(0,[plainText length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
{
int32_t uStyle = self.underlineLinks ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone;
UIColor* thisLinkColor = (self.delegate && [self.delegate respondsToSelector:@selector(colorForLink:underlineStyle:)])
? [self.delegate colorForLink:result underlineStyle:&uStyle] : self.linkColor;
if (thisLinkColor)
[str setTextColor:thisLinkColor range:[result range]];
if (uStyle>0)
[str setTextUnderlineStyle:uStyle range:[result range]];
}];
}
[customLinks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
NSTextCheckingResult* result = (NSTextCheckingResult*)obj;
int32_t uStyle = self.underlineLinks ? kCTUnderlineStyleSingle : kCTUnderlineStyleNone;
UIColor* thisLinkColor = (self.delegate && [self.delegate respondsToSelector:@selector(colorForLink:underlineStyle:)])
? [self.delegate colorForLink:result underlineStyle:&uStyle] : self.linkColor;
@try {
if (thisLinkColor)
[str setTextColor:thisLinkColor range:[result range]];
if (uStyle>0)
[str setTextUnderlineStyle:uStyle range:[result range]];
}
@catch (NSException * e) {
// Protection against NSRangeException
if ([[e name] isEqualToString:NSRangeException]) {
NSLog(@"[OHAttributedLabel] exception: %@",e);
} else {
@throw;
}
}
}];
return [str autorelease];
}
-(NSTextCheckingResult*)linkAtCharacterIndex:(CFIndex)idx {
__block NSTextCheckingResult* foundResult = nil;
NSString* plainText = [_attributedText string];
if (plainText && (self.automaticallyAddLinksForType > 0)) {
NSError* error = nil;
NSDataDetector* linkDetector = [NSDataDetector dataDetectorWithTypes:self.automaticallyAddLinksForType error:&error];
[linkDetector enumerateMatchesInString:plainText options:0 range:NSMakeRange(0,[plainText length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
{
NSRange r = [result range];
if (NSLocationInRange(idx, r)) {
foundResult = [[result retain] autorelease];
*stop = YES;
}
}];
if (foundResult) return foundResult;
}
[customLinks enumerateObjectsUsingBlock:^(id obj, NSUInteger aidx, BOOL *stop)
{
NSRange r = [(NSTextCheckingResult*)obj range];
if (NSLocationInRange(idx, r)) {
foundResult = [[obj retain] autorelease];
*stop = YES;
}
}];
return foundResult;
}
-(NSTextCheckingResult*)linkAtPoint:(CGPoint)point {
static const CGFloat kVMargin = 5.f;
if (!CGRectContainsPoint(CGRectInset(drawingRect, 0, -kVMargin), point)) return nil;
CFArrayRef lines = CTFrameGetLines(textFrame);
if (!lines) return nil;
CFIndex nbLines = CFArrayGetCount(lines);
NSTextCheckingResult* link = nil;
CGPoint origins[nbLines];
CTFrameGetLineOrigins(textFrame, CFRangeMake(0,0), origins);
for (int lineIndex=0 ; lineIndex<nbLines ; ++lineIndex) {
// this actually the origin of the line rect, so we need the whole rect to flip it
CGPoint lineOriginFlipped = origins[lineIndex];
CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
CGRect lineRectFlipped = CTLineGetTypographicBoundsAsRect(line, lineOriginFlipped);
CGRect lineRect = CGRectFlipped(lineRectFlipped, CGRectFlipped(drawingRect,self.bounds));
lineRect = CGRectInset(lineRect, 0, -kVMargin);
if (CGRectContainsPoint(lineRect, point)) {
CGPoint relativePoint = CGPointMake(point.x-CGRectGetMinX(lineRect),
point.y-CGRectGetMinY(lineRect));
CFIndex idx = CTLineGetStringIndexForPosition(line, relativePoint);
link = ([self linkAtCharacterIndex:idx]);
if (link) return link;
}
}
return nil;
}
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// never return self. always return the result of [super hitTest..].
// this takes userInteraction state, enabled, alpha values etc. into account
UIView *hitResult = [super hitTest:point withEvent:event];
// don't check for links if the event was handled by one of the subviews
if (hitResult != self) {
return hitResult;
}
if (self.onlyCatchTouchesOnLinks) {
BOOL didHitLink = ([self linkAtPoint:point] != nil);
if (!didHitLink) {
// not catch the touch if it didn't hit a link
return nil;
}
}
return hitResult;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
CGPoint pt = [touch locationInView:self];
[activeLink release];
activeLink = [[self linkAtPoint:pt] retain];
touchStartPoint = pt;
// we're using activeLink to draw a highlight in -drawRect:
[self setNeedsDisplay];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
CGPoint pt = [touch locationInView:self];
NSTextCheckingResult *linkAtTouchesEnded = [self linkAtPoint:pt];
BOOL closeToStart = (abs(touchStartPoint.x - pt.x) < 10 && abs(touchStartPoint.y - pt.y) < 10);
// we can check on equality of the ranges themselfes since the data detectors create new results
if (activeLink && (NSEqualRanges(activeLink.range,linkAtTouchesEnded.range) || closeToStart)) {
BOOL openLink = (self.delegate && [self.delegate respondsToSelector:@selector(attributedLabel:shouldFollowLink:)])
? [self.delegate attributedLabel:self shouldFollowLink:activeLink] : YES;
if (openLink) [[UIApplication sharedApplication] openURL:activeLink.URL];
}
[activeLink release];
activeLink = nil;
[self setNeedsDisplay];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[activeLink release];
activeLink = nil;
[self setNeedsDisplay];
}
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: Drawing Text
/////////////////////////////////////////////////////////////////////////////
-(void)resetTextFrame {
if (textFrame) {
CFRelease(textFrame);
textFrame = NULL;
}
}
- (void)drawTextInRect:(CGRect)aRect
{
if (_attributedText) {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
// flipping the context to draw core text
// no need to flip our typographical bounds from now on
CGContextConcatCTM(ctx, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f));
if (self.shadowColor) {
CGContextSetShadowWithColor(ctx, self.shadowOffset, 0.0, self.shadowColor.CGColor);
}
NSMutableAttributedString* attrStrWithLinks = [self attributedTextWithLinks];
if (self.highlighted && self.highlightedTextColor != nil) {
[attrStrWithLinks setTextColor:self.highlightedTextColor];
}
if (textFrame == NULL) {
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrStrWithLinks);
drawingRect = self.bounds;
if (self.centerVertically || self.extendBottomToFit) {
CGSize sz = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0,0),NULL,CGSizeMake(drawingRect.size.width,CGFLOAT_MAX),NULL);
if (self.extendBottomToFit) {
CGFloat delta = MAX(0.f , ceilf(sz.height - drawingRect.size.height)) + 10 /* Security margin */;
drawingRect.origin.y -= delta;
drawingRect.size.height += delta;
}
if (self.centerVertically) {
drawingRect.origin.y -= (drawingRect.size.height - sz.height)/2;
}
}
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, drawingRect);
textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
CGPathRelease(path);
CFRelease(framesetter);
}
// draw highlights for activeLink
if (activeLink) {
[self drawActiveLinkHighlightForRect:drawingRect];
}
CTFrameDraw(textFrame, ctx);
CGContextRestoreGState(ctx);
} else {
[super drawTextInRect:aRect];
}
}
-(void)drawActiveLinkHighlightForRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextConcatCTM(ctx, CGAffineTransformMakeTranslation(rect.origin.x, rect.origin.y));
[self.highlightedLinkColor setFill];
NSRange activeLinkRange = activeLink.range;
CFArrayRef lines = CTFrameGetLines(textFrame);
CFIndex lineCount = CFArrayGetCount(lines);
CGPoint lineOrigins[lineCount];
CTFrameGetLineOrigins(textFrame, CFRangeMake(0,0), lineOrigins);
for (CFIndex lineIndex = 0; lineIndex < lineCount; lineIndex++) {
CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
if (!CTLineContainsCharactersFromStringRange(line, activeLinkRange)) {
continue; // with next line
}
// we use this rect to union the bounds of successive runs that belong to the same active link
CGRect unionRect = CGRectZero;
CFArrayRef runs = CTLineGetGlyphRuns(line);
CFIndex runCount = CFArrayGetCount(runs);
for (CFIndex runIndex = 0; runIndex < runCount; runIndex++) {
CTRunRef run = CFArrayGetValueAtIndex(runs, runIndex);
if (!CTRunContainsCharactersFromStringRange(run, activeLinkRange)) {
if (!CGRectIsEmpty(unionRect)) {
CGContextFillRect(ctx, unionRect);
unionRect = CGRectZero;
}
continue; // with next run
}
CGRect linkRunRect = CTRunGetTypographicBoundsAsRect(run, line, lineOrigins[lineIndex]);
linkRunRect = CGRectIntegral(linkRunRect); // putting the rect on pixel edges
linkRunRect = CGRectInset(linkRunRect, -1, -1); // increase the rect a little
if (CGRectIsEmpty(unionRect)) {
unionRect = linkRunRect;
} else {
unionRect = CGRectUnion(unionRect, linkRunRect);
}
}
if (!CGRectIsEmpty(unionRect)) {
CGContextFillRect(ctx, unionRect);
//unionRect = CGRectZero;
}
}
CGContextRestoreGState(ctx);
}
- (CGSize)sizeThatFits:(CGSize)size {
NSMutableAttributedString* attrStrWithLinks = [self attributedTextWithLinks];
if (!attrStrWithLinks) return CGSizeZero;
return [attrStrWithLinks sizeConstrainedToSize:size fitRange:NULL];
}
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: Setters/Getters
/////////////////////////////////////////////////////////////////////////////
@synthesize linkColor, highlightedLinkColor, underlineLinks;
@synthesize centerVertically, automaticallyAddLinksForType, onlyCatchTouchesOnLinks, extendBottomToFit;
@synthesize delegate;
/////////////////////////////////////////////////////////////////////////////
// MARK: -
/////////////////////////////////////////////////////////////////////////////
-(void)resetAttributedText {
NSMutableAttributedString* mutAttrStr = [NSMutableAttributedString attributedStringWithString:self.text];
[mutAttrStr setFont:self.font];
[mutAttrStr setTextColor:self.textColor];
CTTextAlignment coreTextAlign = CTTextAlignmentFromUITextAlignment(self.textAlignment);
CTLineBreakMode coreTextLBMode = CTLineBreakModeFromUILineBreakMode(self.lineBreakMode);
[mutAttrStr setTextAlignment:coreTextAlign lineBreakMode:coreTextLBMode lineHeight:self.font.lineHeight];
self.attributedText = mutAttrStr;
}
-(NSAttributedString*)attributedText {
if (!_attributedText) {
[self resetAttributedText];
}
return [[_attributedText copy] autorelease]; // immutable autoreleased copy
}
-(void)setAttributedText:(NSAttributedString*)attributedText {
[_attributedText release];
_attributedText = [attributedText mutableCopy];
[self setAccessibilityLabel:_attributedText.string];
[self removeAllCustomLinks];
[self setNeedsDisplay];
}
/////////////////////////////////////////////////////////////////////////////
-(void)setText:(NSString *)text {
NSString* cleanedText = [[text stringByReplacingOccurrencesOfString:@"\r\n" withString:@"\n"]
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[super setText:cleanedText]; // will call setNeedsDisplay too
[self resetAttributedText];
}
-(void)setFont:(UIFont *)font {
[_attributedText setFont:font];
[super setFont:font]; // will call setNeedsDisplay too
}
-(void)setTextColor:(UIColor *)color {
[_attributedText setTextColor:color];
[super setTextColor:color]; // will call setNeedsDisplay too
}
-(void)setTextAlignment:(UITextAlignment)alignment {
CTTextAlignment coreTextAlign = CTTextAlignmentFromUITextAlignment(alignment);
CTLineBreakMode coreTextLBMode = CTLineBreakModeFromUILineBreakMode(self.lineBreakMode);
[_attributedText setTextAlignment:coreTextAlign lineBreakMode:coreTextLBMode lineHeight:self.font.lineHeight];
[super setTextAlignment:alignment]; // will call setNeedsDisplay too
}
-(void)setLineBreakMode:(UILineBreakMode)lineBreakMode {
CTTextAlignment coreTextAlign = CTTextAlignmentFromUITextAlignment(self.textAlignment);
CTLineBreakMode coreTextLBMode = CTLineBreakModeFromUILineBreakMode(lineBreakMode);
[_attributedText setTextAlignment:coreTextAlign lineBreakMode:coreTextLBMode lineHeight:self.font.lineHeight];
[super setLineBreakMode:lineBreakMode]; // will call setNeedsDisplay too
#if OHAttributedLabel_WarnAboutKnownIssues
[self warnAboutKnownIssues_CheckLineBreakMode];
#endif
}
-(void)setCenterVertically:(BOOL)val {
centerVertically = val;
[self setNeedsDisplay];
}
-(void)setAutomaticallyAddLinksForType:(NSTextCheckingTypes)types {
automaticallyAddLinksForType = types;
[self setNeedsDisplay];
}
-(void)setExtendBottomToFit:(BOOL)val {
extendBottomToFit = val;
[self setNeedsDisplay];
}
-(void)setNeedsDisplay {
[self resetTextFrame];
[super setNeedsDisplay];
}
/////////////////////////////////////////////////////////////////////////////
// MARK: -
// MARK: UILabel unsupported features/known issues warnings
/////////////////////////////////////////////////////////////////////////////
#if OHAttributedLabel_WarnAboutKnownIssues
-(void)warnAboutKnownIssues_CheckLineBreakMode {
BOOL truncationMode = (self.lineBreakMode == UILineBreakModeHeadTruncation)
|| (self.lineBreakMode == UILineBreakModeMiddleTruncation)
|| (self.lineBreakMode == NSLineBreakByTruncatingTail);
if (truncationMode) {
NSLog(@"[OHAttributedLabel] Warning: \"UILineBreakMode...Truncation\" lineBreakModes not yet fully supported by CoreText and OHAttributedLabel");
NSLog(@" (truncation will appear on each paragraph instead of the whole text)");
NSLog(@" This is a known issue (Help to solve this would be greatly appreciated).");
NSLog(@" See https://github.com/AliSoftware/OHAttributedLabel/issues/3");
}
}
-(void)warnAboutKnownIssues_CheckAdjustsFontSizeToFitWidth {
if (self.adjustsFontSizeToFitWidth) {
NSLog(@"[OHAttributedLabel] Warning: \"adjustsFontSizeToFitWidth\" property not supported by CoreText and OHAttributedLabel! This property will be ignored.");
}
}
-(void)setAdjustsFontSizeToFitWidth:(BOOL)value {
[super setAdjustsFontSizeToFitWidth:value];
[self warnAboutKnownIssues_CheckAdjustsFontSizeToFitWidth];
}
-(void)setNumberOfLines:(NSInteger)nbLines {
NSLog(@"[OHAttributedLabel] Warning: the numberOfLines property is not yet supported by CoreText and OHAttributedLabel. (this property is ignored right now)");
NSLog(@" This is a known issue (Help to solve this would be greatly appreciated).");
NSLog(@" See https://github.com/AliSoftware/OHAttributedLabel/issues/34");
[super setNumberOfLines:nbLines];
}
#endif
@end

View file

@ -111,11 +111,14 @@
self.connection = nil;
if ([responseString compare:RESPONSE_SUCCESS] == NSOrderedSame) {
[self.delegate instapaperAddRequestSucceded:self];
if ([self.delegate respondsToSelector:@selector(instapaperAddRequestSucceded:)])
[self.delegate instapaperAddRequestSucceded:self];
} else if ([responseString compare:RESPONSE_PASSWORD_INCORRECT] == NSOrderedSame) {
[self.delegate instapaperAddRequestIncorrectPassword:self];
if ([self.delegate respondsToSelector:@selector(instapaperAddRequestIncorrectPassword:)])
[self.delegate instapaperAddRequestIncorrectPassword:self];
} else {
[self.delegate instapaperAddRequestFailed:self];
if ([self.delegate respondsToSelector:@selector(instapaperAddRequestFailed:)])
[self.delegate instapaperAddRequestFailed:self];
}
}

View file

@ -2,10 +2,10 @@
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1552</int>
<string key="IBDocument.SystemVersion">12C3006</string>
<string key="IBDocument.SystemVersion">12F37</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.34</string>
<string key="IBDocument.HIToolboxVersion">625.00</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">2083</string>
@ -228,6 +228,7 @@
<string key="NSFrameSize">{320, 44}</string>
<reference key="NSSuperview" ref="612255706"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="864978609"/>
<string key="NSReuseIdentifierKey">_NS:240</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<array key="IBUIItems">
@ -257,6 +258,7 @@
<string key="NSFrame">{{0, 244}, {320, 216}}</string>
<reference key="NSSuperview" ref="612255706"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:624</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBUIShowsSelectionIndicator">YES</bool>
@ -612,6 +614,7 @@
<string key="41.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="42.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="43.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="44.CustomClassName">FolderTextField</string>
<string key="44.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
@ -890,6 +893,7 @@
<string key="spacer3BarButton">UIBarButtonItem</string>
<string key="spacerBarButton">UIBarButtonItem</string>
<string key="storyTitlesTable">UITableView</string>
<string key="titleImageBarButton">UIBarButtonItem</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="appDelegate">
@ -928,6 +932,10 @@
<string key="name">storyTitlesTable</string>
<string key="candidateClassName">UITableView</string>
</object>
<object class="IBToOneOutletInfo" key="titleImageBarButton">
<string key="name">titleImageBarButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
@ -939,6 +947,7 @@
<string key="superclassName">UIViewController</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="appDelegate">NewsBlurAppDelegate</string>
<string key="loginAsAlert">UIAlertView</string>
<string key="menuTableView">UITableView</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
@ -946,6 +955,10 @@
<string key="name">appDelegate</string>
<string key="candidateClassName">NewsBlurAppDelegate</string>
</object>
<object class="IBToOneOutletInfo" key="loginAsAlert">
<string key="name">loginAsAlert</string>
<string key="candidateClassName">UIAlertView</string>
</object>
<object class="IBToOneOutletInfo" key="menuTableView">
<string key="name">menuTableView</string>
<string key="candidateClassName">UITableView</string>
@ -1184,6 +1197,14 @@
<string key="minorKey">./Classes/FirstTimeUserViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">FolderTextField</string>
<string key="superclassName">UITextField</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/FolderTextField.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">FontSettingsViewController</string>
<string key="superclassName">UIViewController</string>
@ -1267,6 +1288,25 @@
<string key="minorKey">./Classes/FriendsListViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">IASKAppSettingsViewController</string>
<string key="superclassName">UITableViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">delegate</string>
<string key="NS.object.0">id</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">delegate</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">delegate</string>
<string key="candidateClassName">id</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/IASKAppSettingsViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">InteractionsModule</string>
<string key="superclassName">UIView</string>
@ -1434,12 +1474,12 @@
<string key="cancelButton">UIBarButtonItem</string>
<string key="errorLabel">UILabel</string>
<string key="folderPicker">UIPickerView</string>
<string key="fromFolderInput">UITextField</string>
<string key="fromFolderInput">FolderTextField</string>
<string key="moveButton">UIBarButtonItem</string>
<string key="movingLabel">UILabel</string>
<string key="navBar">UINavigationBar</string>
<string key="titleLabel">UILabel</string>
<string key="toFolderInput">UITextField</string>
<string key="toFolderInput">FolderTextField</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="activityIndicator">
@ -1464,7 +1504,7 @@
</object>
<object class="IBToOneOutletInfo" key="fromFolderInput">
<string key="name">fromFolderInput</string>
<string key="candidateClassName">UITextField</string>
<string key="candidateClassName">FolderTextField</string>
</object>
<object class="IBToOneOutletInfo" key="moveButton">
<string key="name">moveButton</string>
@ -1484,7 +1524,7 @@
</object>
<object class="IBToOneOutletInfo" key="toFolderInput">
<string key="name">toFolderInput</string>
<string key="candidateClassName">UITextField</string>
<string key="candidateClassName">FolderTextField</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@ -1542,6 +1582,7 @@
<string key="moveSiteViewController">MoveSiteViewController</string>
<string key="navigationController">UINavigationController</string>
<string key="originalStoryViewController">OriginalStoryViewController</string>
<string key="preferencesViewController">IASKAppSettingsViewController</string>
<string key="shareViewController">ShareViewController</string>
<string key="storyDetailViewController">StoryDetailViewController</string>
<string key="storyPageControl">StoryPageControl</string>
@ -1626,6 +1667,10 @@
<string key="name">originalStoryViewController</string>
<string key="candidateClassName">OriginalStoryViewController</string>
</object>
<object class="IBToOneOutletInfo" key="preferencesViewController">
<string key="name">preferencesViewController</string>
<string key="candidateClassName">IASKAppSettingsViewController</string>
</object>
<object class="IBToOneOutletInfo" key="shareViewController">
<string key="name">shareViewController</string>
<string key="candidateClassName">ShareViewController</string>
@ -1772,7 +1817,7 @@
<string key="superclassName">BaseViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="doCloseOriginalStoryViewController">id</string>
<string key="doOpenActionSheet">id</string>
<string key="doOpenActionSheet:">id</string>
<string key="loadAddress:">id</string>
<string key="webViewGoBack:">id</string>
<string key="webViewGoForward:">id</string>
@ -1783,8 +1828,8 @@
<string key="name">doCloseOriginalStoryViewController</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="doOpenActionSheet">
<string key="name">doOpenActionSheet</string>
<object class="IBActionInfo" key="doOpenActionSheet:">
<string key="name">doOpenActionSheet:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="loadAddress:">
@ -1865,7 +1910,7 @@
</object>
<object class="IBPartialClassDescription">
<string key="className">ShareViewController</string>
<string key="superclassName">UIViewController</string>
<string key="superclassName">BaseViewController</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="doCancelButton:">id</string>
<string key="doReplyToComment:">id</string>
@ -1982,9 +2027,11 @@
<dictionary class="NSMutableDictionary" key="actions">
<string key="doNextUnreadStory">id</string>
<string key="doPreviousStory">id</string>
<string key="openSendToDialog:">id</string>
<string key="showOriginalSubview:">id</string>
<string key="tapProgressBar:">id</string>
<string key="toggleFontSize:">id</string>
<string key="toggleView:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="doNextUnreadStory">
@ -1995,6 +2042,10 @@
<string key="name">doPreviousStory</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="openSendToDialog:">
<string key="name">openSendToDialog:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showOriginalSubview:">
<string key="name">showOriginalSubview:</string>
<string key="candidateClassName">id</string>
@ -2007,6 +2058,10 @@
<string key="name">toggleFontSize:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="toggleView:">
<string key="name">toggleView:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="appDelegate">NewsBlurAppDelegate</string>
@ -2014,11 +2069,14 @@
<string key="buttonAction">UIBarButtonItem</string>
<string key="buttonNext">UIButton</string>
<string key="buttonPrevious">UIButton</string>
<string key="buttonSend">UIButton</string>
<string key="buttonText">UIButton</string>
<string key="circularProgressView">THCircularProgressView</string>
<string key="fontSettingsButton">UIBarButtonItem</string>
<string key="loadingIndicator">UIActivityIndicatorView</string>
<string key="originalStoryButton">UIBarButtonItem</string>
<string key="pageControl">UIPageControl</string>
<string key="progressView">UIProgressView</string>
<string key="progressView">UIView</string>
<string key="progressViewContainer">UIView</string>
<string key="rightToolbar">TransparentToolbar</string>
<string key="scrollView">UIScrollView</string>
@ -2050,6 +2108,18 @@
<string key="name">buttonPrevious</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonSend">
<string key="name">buttonSend</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="buttonText">
<string key="name">buttonText</string>
<string key="candidateClassName">UIButton</string>
</object>
<object class="IBToOneOutletInfo" key="circularProgressView">
<string key="name">circularProgressView</string>
<string key="candidateClassName">THCircularProgressView</string>
</object>
<object class="IBToOneOutletInfo" key="fontSettingsButton">
<string key="name">fontSettingsButton</string>
<string key="candidateClassName">UIBarButtonItem</string>
@ -2068,7 +2138,7 @@
</object>
<object class="IBToOneOutletInfo" key="progressView">
<string key="name">progressView</string>
<string key="candidateClassName">UIProgressView</string>
<string key="candidateClassName">UIView</string>
</object>
<object class="IBToOneOutletInfo" key="progressViewContainer">
<string key="name">progressViewContainer</string>
@ -2112,6 +2182,14 @@
<string key="minorKey">./Classes/StoryPageControl.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">THCircularProgressView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/THCircularProgressView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">TrainerViewController</string>
<string key="superclassName">BaseViewController</string>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View file

@ -587,7 +587,7 @@ a.NB-show-profile {
}
.NB-button.NB-share-button:active div {
color: white;
color: darkgrey;
text-shadow: 0 1px 0 rgba(0, 0, 0, .2);
}
.NB-iphone .NB-button div {

View file

@ -1111,22 +1111,27 @@ background: transparent;
margin-left: 220px;
}
.NB-feedbar {
.NB-story-titles-header {
font-weight: bold;
font-size: 16px;
padding: 2px 208px 2px 4px;
padding: 6px 24px 0px 8px;
position: relative;
overflow: hidden;
}
.NB-feedbar {
background-image: -webkit-gradient(linear, left top, left bottom, from(#FEFEFE), to(#F3F4EF));
background-image: -moz-linear-gradient(center top , #FEFEFE 0%, #F3F4EF 100%);
background-image: linear-gradient(top, #FEFEFE, #F3F4EF);
border-bottom: 1px solid #C2C5BE;
position: relative;
overflow: hidden;
}
.NB-story-pane-west .NB-feedbar {
padding-right: 4px;
background-color: #F3F3EE;
background-image: -webkit-gradient(linear, left top, left bottom, from(#F3F3EE), to(#E8EBE4));
background-image: -moz-linear-gradient(center top , #F3F3EE 0%, #E8EBE4 100%);
background-image: linear-gradient(top, #F3F3EE, #E8EBE4);
}
.NB-feedbar .feed .feed_favicon {
margin: 2px 4px 0 2px;
margin: 4px 4px 0 6px;
vertical-align: top;
float: left;
width: 16px;
@ -1138,35 +1143,24 @@ background: transparent;
.NB-feedbar .feed .feed_title,
.NB-feedbar .folder_title_text {
/* float: left;*/
display: block;
margin-left: 24px;
color: #40413E;
text-shadow: 0 1px 0 rgba(255, 255, 255, .8);
display: block;
margin-left: 26px;
color: #40413E;
text-shadow: 0 1px 0 rgba(255, 255, 255, .8);
height: 24px;
overflow: hidden;
line-height: 24px;
text-overflow: ellipsis;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
display: -webkit-box;
}
.NB-feedbar .NB-feedbar-options-container {
position: absolute;
right: 0;
width: 206px;
top: 2px;
}
.NB-story-pane-west .NB-feedbar .NB-feedbar-options-container {
position: static;
margin: 4px 0 5px 24px;
overflow: hidden;
float: left;
width: auto;
}
.NB-story-pane-west .NB-feedbar .NB-story-title-search {
position: relative;
margin: 2px 0 8px 28px; /* 24+4 takes the border into account */
float: left;
}
.NB-story-pane-west .NB-feedbar .NB-story-title-search input {
float: left;
float: right;
}
.NB-feedbar .NB-feedbar-options {
cursor: pointer;
float: left;
float: right;
color: rgba(0, 0, 0, .5);
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 16px;
@ -1174,12 +1168,7 @@ background: transparent;
font-size: 10px;
padding: 1px 4px 1px 8px;
line-height: 14px;
margin: 1px 0 0;
-webkit-transition: all .12s ease-out;
-moz-transition: all .12s ease-out;
-o-transition: all .12s ease-out;
-ms-transition: all .12s ease-out;
margin: 3px 0 0;
}
.NB-feedbar .NB-feedbar-options:hover,
.NB-feedbar .NB-feedbar-options.NB-active {
@ -1212,36 +1201,77 @@ background: transparent;
padding:0 24px 0 6px;
}
.NB-feedbar .NB-feedbar-mark-feed-read {
cursor: pointer;
.NB-feedbar .NB-feedbar-mark-feed-read-container {
position: relative;
margin: 0 10px 0 6px;
font-size: 9px;
line-height: 15px;
font-weight: bold;
margin: 2px 11px -2px;
padding: 0px 4px 0;
float: right;
}
.NB-feedbar .NB-feedbar-mark-feed-read,
.NB-feedbar .NB-feedbar-mark-feed-read-expand,
.NB-feedbar .NB-feedbar-mark-feed-read-time {
cursor: pointer;
position: relative;
padding: 1px 4px;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 16px;
display: inline-block;
background: transparent url('/media/embed/icons/circular/nav_icn_markread.png') no-repeat center center;
background-size: 18px;
float: right;
width: 26px;
height: 14px;
z-index: 1;
margin: 3px 0 0 8px;
-webkit-transition: all .12s ease-out;
-moz-transition: all .12s ease-out;
-o-transition: all .12s ease-out;
-ms-transition: all .12s ease-out;
background-color: #F0F1EC;
background-image: -webkit-gradient(linear, left top, left bottom, from(#F0F1EC), to(#EBEDE7));
background-image: -moz-linear-gradient(center top , #F0F1EC 0%, #EBEDE7 100%);
background-image: linear-gradient(top, #F0F1EC, #EBEDE7);
}
.NB-feedbar .NB-feedbar-mark-feed-read:hover {
.NB-feedbar .NB-feedbar-mark-feed-read .NB-icon {
background: transparent url('/media/embed/icons/circular/nav_icn_markread.png') no-repeat center center;
background-size: 18px;
width: 100%;
height: 100%;
}
.NB-feedbar .NB-feedbar-mark-feed-read:hover,
.NB-feedbar .NB-feedbar-mark-feed-read-time:hover {
background-color: #D8D9D4;
background-image: -webkit-gradient(linear, left top, left bottom, from(#D8D9D4), to(#D4D5D0));
background-image: -moz-linear-gradient(center top , #D8D9D4 0%, #D4D5D0 100%);
background-image: linear-gradient(top, #D8D9D4, #D4D5D0);
}
.NB-feedbar .NB-feedbar-mark-feed-read-expand:hover {
background-color: rgba(0, 0, 0, .1);
}
.NB-feedbar .NB-feedbar-mark-feed-read-expand {
position: absolute;
right: 20px;
z-index: 0;
background: transparent url('/media/embed/icons/circular/nav_icn_plus.png') no-repeat 4px center;
background-size: 6px;
width: 19px;
}
.NB-feedbar .NB-feedbar-mark-feed-read-time {
z-index: 0;
right: 0;
top: 0;
width: 20px;
position: absolute;
text-align: center;
color: rgba(0, 0, 0, .5);
text-transform: uppercase;
}
.NB-feedbar .NB-feedlist-manage-icon {
opacity: 0;
display: none;
position: absolute;
left: 7px;
top: 1px;
left: 10px;
top: 7px;
width: 20px;
height: 22px;
cursor: pointer;
@ -1252,11 +1282,17 @@ background: transparent;
background: transparent url('/media/embed/icons/circular/g_icn_arrow_down.png') no-repeat 6px 7px;
background-size: 8px;
}
.NB-feedbar .NB-folder .NB-feedlist-manage-icon {
top: 7px;
left: 8px;
}
.NB-feedbar .NB-hover-inverse .NB-feedlist-manage-icon:hover {
background: transparent url('/media/embed/icons/circular/g_icn_arrow_up.png') no-repeat 5px 7px;
background: transparent url('/media/embed/icons/circular/g_icn_arrow_up.png') no-repeat 4px 5px;
background-size: 8px;
}
.NB-feedbar .NB-folder.NB-hover-inverse .NB-feedlist-manage-icon:hover {
background-position: 4px 7px;
}
.NB-feedbar:hover :not(.NB-no-hover) .NB-feedlist-manage-icon {
display: block;
@ -1267,9 +1303,6 @@ background: transparent;
.NB-feedbar:hover :not(.NB-no-hover) .NB-folder-icon {
display: none;
}
.NB-feedbar .folder_title .NB-feedlist-manage-icon {
background-position: 3px 5px;
}
.NB-feedbar .feed .feed_counts {
@ -1335,8 +1368,8 @@ background: transparent;
width: 16px;
height: 16px;
position: absolute;
left: 4px;
top: 4px;
left: 12px;
top: 10px;
}
.NB-feedbar .NB-folder .NB-starred-icon {
background: transparent url('/media/embed/icons/circular/clock.png') no-repeat 0 0;
@ -1344,8 +1377,8 @@ background: transparent;
width: 16px;
height: 16px;
position: absolute;
left: 4px;
top: 4px;
left: 12px;
top: 10px;
}
.NB-feedbar .folder ul.folder,
@ -1360,32 +1393,20 @@ background: transparent;
.NB-feedbar .NB-story-title-indicator {
display: none;
position: absolute;
right: 206px;
top: 2px;
float: right;
cursor: pointer;
color: rgba(0, 0, 0, .5);
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 16px;
text-transform: uppercase;
font-size: 10px;
padding: 0 8px;
padding: 1px 8px;
line-height: 14px;
margin: 2px 12px 0;
-webkit-transition: all .12s ease-out;
-moz-transition: all .12s ease-out;
-o-transition: all .12s ease-out;
-ms-transition: all .12s ease-out;
margin: 3px 12px 0;
}
.NB-feedbar .NB-story-title-indicator:hover {
background-color: rgba(0, 0, 0, .1);
}
.NB-story-pane-west .NB-feedbar .NB-story-title-indicator {
position: static;
float: left;
margin: 5px 0px 4px 24px;
}
.NB-feedbar .NB-story-title-indicator .NB-story-title-indicator-count {
float: left;
}
@ -1422,10 +1443,6 @@ background: transparent;
padding: 1px 3px 1px;
margin: 0 4px 0 0;
line-height: 8px;
-webkit-transition: opacity .12s ease-out;
-moz-transition: opacity .12s ease-out;
-o-transition: opacity .12s ease-out;
-ms-transition: opacity .12s ease-out;
}
.NB-intelligence-positive .NB-story-title.NB-story-neutral .NB-hidden-fade,
@ -1621,7 +1638,7 @@ background: transparent;
position: absolute;
}
.NB-story-pane-west #story_titles .NB-story-title .NB-story-feed {
left: -24px;
left: -22px;
}
.NB-view-river #story_titles .NB-story-title .NB-story-feed {
display: block;
@ -3245,7 +3262,7 @@ background: transparent;
/* ====================== */
#story_taskbar .NB-river-progress {
margin: 6px 12px 0;
margin: 3px 12px 0;
width: 150px;
height: 20px;
}
@ -3273,7 +3290,7 @@ background: transparent;
/* ============== */
#story_taskbar .NB-feed-error {
margin: 6px 12px 0;
margin: 2px 12px 0;
height: 20px;
}
@ -3302,12 +3319,12 @@ background: transparent;
#story_taskbar .feed_counts_floater {
position: absolute;
bottom: 1px;
bottom: 2px;
left: 350px;
height: 30px;
height: 27px;
z-index: 10;
display: block;
font-size: 20px;
font-size: 19px;
}
.NB-is-anonymous #story_taskbar .feed_counts_floater {
display: none;
@ -3606,7 +3623,6 @@ background: transparent;
/* ============ */
.NB-taskbar-container {
border-bottom: 1px solid #C2C5BE;
text-shadow: 0 1px 0 rgba(255, 255, 255, .8);
background-color: #F3F3EE;
background-image: -webkit-gradient(linear, left top, left bottom, from(#F3F3EE), to(#E8EBE4));
@ -3694,17 +3710,27 @@ background: transparent;
#story_taskbar {
overflow: hidden;
display: none;
border-top: 1px solid #C2C5BE;
}
#story_taskbar .feed_counts_floater .unread_count {
margin-top: 1px;
text-shadow: none;
}
#story_taskbar .NB-taskbar {
margin: 5px 0 0 0;
margin: 3px 0 0 0;
}
.NB-feedbar .NB-taskbar {
margin: 2px 0 0 0;
}
#story_taskbar .NB-taskbar .NB-taskbar-button {
font-size: 11px;
padding: 4px 8px 3px;
padding: 2px 8px 2px;
line-height: 18px;
position: relative;
}
.NB-feedbar .NB-taskbar .NB-taskbar-button {
font-size: 11px;
padding: 3px 8px;
line-height: 18px;
position: relative;
}
@ -3714,9 +3740,10 @@ background: transparent;
margin-left: 6px;
}
#story_taskbar .NB-taskbar-nav {
.NB-feedbar .NB-taskbar-nav {
float: right;
margin-right: 18px;
margin: 6px 18px 0 0;
font-weight: normal;
}
#story_taskbar .NB-taskbar-layout {
float: right;
@ -3906,12 +3933,6 @@ background: transparent;
border-bottom: 1px solid #C2C5BE;
}
.NB-story-pane-north .NB-taskbar-container,
.NB-story-pane-west .NB-taskbar-container {
border-top: none;
border-bottom: 1px solid #777D86;
}
/* ==================== */
/* = OPML Import Form = */
/* ==================== */
@ -10051,10 +10072,13 @@ form.opml_import_form input {
.NB-searching .NB-search-close {
display: block;
}
.NB-search-container {
position: relative;
}
.NB-story-title-search {
position: absolute;
top: 3px;
right: 4px;
float: right;
margin: 3px 0 0 12px;
position: relative;
}
.NB-story-title-search-input {
-webkit-transition: all .22s ease-in-out;
@ -10104,11 +10128,13 @@ form.opml_import_form input {
margin-left: 200px;
}
<<<<<<< HEAD
/* ======================== */
/* = Feed Options Popover = */
/* ======================== */
.NB-filter-popover-container.popover.bottom-left .arrow {
left: 20%;
}
.NB-filter-popover-container .popover-content {
padding: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

View file

@ -267,18 +267,21 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
}, pre_callback);
},
mark_feed_as_read: function(feed_id, callback) {
mark_feed_as_read: function(feed_id, cutoff_timestamp, mark_active, callback) {
var self = this;
var feed_ids = _.isArray(feed_id)
? _.select(feed_id, function(f) { return f; })
: [feed_id];
this.make_request('/reader/mark_feed_as_read', {
feed_id: feed_ids
feed_id: feed_ids,
cutoff_timestamp: cutoff_timestamp
}, callback);
if (feed_id == NEWSBLUR.reader.active_feed) {
if (mark_active) {
this.stories.each(function(story) {
if (cutoff_timestamp &&
parseInt(story.get('story_timestamp'), 10) > cutoff_timestamp) return;
story.set('read_status', true);
});
}
@ -587,6 +590,13 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
var self = this;
var pre_callback = function(data) {
if (!NEWSBLUR.Globals.is_premium && NEWSBLUR.Globals.is_authenticated) {
if (first_load) {
data.stories = data.stories.splice(0, 5);
} else {
data.stories = [];
}
}
self.load_feed_precallback(data, feed_id, callback, first_load);
};

View file

@ -34,7 +34,7 @@ NEWSBLUR.Modal.prototype = {
}
});
setTimeout(function() {
$(window).resize();
// $(window).resize();
self.flags.modal_loaded = true;
});
});
@ -59,7 +59,7 @@ NEWSBLUR.Modal.prototype = {
},
resize: function() {
$(window).trigger('resize.simplemodal');
// $(window).trigger('resize.simplemodal');
},
close: function(callback) {

View file

@ -47,8 +47,11 @@ NEWSBLUR.Models.Feed = Backbone.Model.extend({
delete_feed: function(options) {
options = options || {};
var view = options.view || this.get_view();
NEWSBLUR.assets.delete_feed(this.id, view.options.folder_title);
NEWSBLUR.reader.flags['reloading_feeds'] = true;
NEWSBLUR.assets.delete_feed(this.id, view.options.folder_title, function() {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
});
view.delete_feed();
},
@ -58,8 +61,10 @@ NEWSBLUR.Models.Feed = Backbone.Model.extend({
var in_folder = view.options.folder_title;
if (in_folder == to_folder) return false;
NEWSBLUR.reader.flags['reloading_feeds'] = true;
NEWSBLUR.assets.move_feed_to_folder(this.id, in_folder, to_folder, function() {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
_.delay(function() {
NEWSBLUR.reader.$s.$feed_list.css('opacity', 1).animate({'opacity': 0}, {
'duration': 100,

View file

@ -75,7 +75,9 @@ NEWSBLUR.Models.FeedOrFolder = Backbone.Model.extend({
var folder_title = this.get('folder_title');
if (in_folder == to_folder) return false;
NEWSBLUR.reader.flags['reloading_feeds'] = true;
NEWSBLUR.assets.move_folder_to_folder(folder_title, in_folder, to_folder, function() {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
_.delay(function() {
NEWSBLUR.reader.$s.$feed_list.css('opacity', 1).animate({'opacity': 0}, {
'duration': 100,
@ -100,7 +102,11 @@ NEWSBLUR.Models.FeedOrFolder = Backbone.Model.extend({
var folder_title = this.get('folder_title');
var in_folder = this.collection.options.title;
var feed_ids_in_folder = this.feed_ids_in_folder();
NEWSBLUR.assets.delete_folder(folder_title, in_folder, feed_ids_in_folder);
NEWSBLUR.reader.flags['reloading_feeds'] = true;
NEWSBLUR.assets.delete_folder(folder_title, in_folder, feed_ids_in_folder, function() {
NEWSBLUR.reader.flags['reloading_feeds'] = false;
});
this.trigger('delete');
},

View file

@ -23,6 +23,7 @@
$social_feeds: $('.NB-socialfeeds-folder'),
$starred_feeds: $('.NB-starred-folder'),
$story_titles: $('#story_titles'),
$story_titles_header: $('.NB-story-titles-header'),
$content_pane: $('.content-pane'),
$story_taskbar: $('#story_taskbar'),
$story_pane: $('#story_pane .NB-story-pane-container'),
@ -327,7 +328,9 @@
fxSettings_close: { duration: 560, easing: "easeInOutQuint" },
fxSettings_open: { duration: 0, easing: "easeInOutQuint" },
north__paneSelector: ".content-north",
north__size: 37
north__size: 37,
south__paneSelector: ".content-south",
south__size: 31
};
this.layout.rightLayout = $('.right-pane').layout(rightLayoutOptions);
@ -367,7 +370,9 @@
fxName: "slideOffscreen",
fxSettings: { duration: 560, easing: "easeInOutQuint" },
north__paneSelector: ".content-north",
north__size: 37
north__size: 37,
south__paneSelector: ".content-south",
south__size: 31
};
this.layout.rightLayout = $('.right-pane').layout(rightLayoutOptions);
@ -407,9 +412,9 @@
gravity: 's',
delayIn: 375
}).tipsy('enable');
$('.NB-narrow .NB-taskbar-button.NB-tipsy').tipsy({
gravity: 'n',
delayIn: 375,
$('.NB-narrow .NB-taskbar-button.NB-tipsy, .NB-task-layout-split').tipsy({
gravity: 's',
delayIn: 175,
title: 'tipsy-title'
}).each(function() {
$(this).tipsy('enable');
@ -1100,7 +1105,8 @@
'social_view': false,
'starred_view': false,
'select_story_in_feed': null,
'global_blurblogs': false
'global_blurblogs': false,
'reloading_feeds': false
});
$.extend(this.cache, {
@ -1449,9 +1455,11 @@
this.switch_to_correct_view();
this.make_feed_title_in_stories();
_.defer(function() {
NEWSBLUR.app.story_titles.scroll_to_selected_story();
NEWSBLUR.app.story_list.scroll_to_selected_story();
NEWSBLUR.app.feed_list.scroll_to_selected();
if (_.contains(['split', 'list'], NEWSBLUR.assets.preference('story_layout'))) {
NEWSBLUR.app.story_titles.fill_out();
} else {
@ -1954,44 +1962,35 @@
}
},
mark_feed_as_read: function(feed_id) {
mark_feed_as_read: function(feed_id, days_back) {
feed_id = feed_id || this.active_feed;
this.model.mark_feed_as_read([feed_id]);
this.mark_feed_as_read_update_counts(feed_id);
if (feed_id == this.active_feed) {
this.model.stories.each(function(story) {
story.set('read_status', true);
});
var cutoff_timestamp = NEWSBLUR.utils.days_back_to_timestamp(days_back);
if (!days_back && this.model.stories.length &&
this.model.stories.first().get('story_feed_id') == feed_id &&
NEWSBLUR.assets.view_setting(feed_id, 'order') == 'newest') {
cutoff_timestamp = this.model.stories.first().get('story_timestamp');
}
this.model.mark_feed_as_read([feed_id], cutoff_timestamp, feed_id == this.active_feed, _.bind(function() {
this.feeds_unread_count(feed_id);
}, this));
},
mark_folder_as_read: function(folder) {
mark_folder_as_read: function(folder, days_back) {
var folder = folder || this.active_folder;
var feeds = folder.feed_ids_in_folder();
this.model.mark_feed_as_read(feeds);
_.each(feeds, _.bind(function(feed_id) {
this.mark_feed_as_read_update_counts(feed_id);
}, this));
var cutoff_timestamp = NEWSBLUR.utils.days_back_to_timestamp(days_back);
if (!days_back && this.model.stories.length &&
_.contains(feeds, this.model.stories.first().get('story_feed_id')) &&
NEWSBLUR.assets.view_setting(folder.id, 'order') == 'newest') {
cutoff_timestamp = this.model.stories.first().get('story_timestamp');
}
if (folder == this.active_folder) {
this.model.stories.each(function(story) {
story.set('read_status', true);
});
}
},
mark_feed_as_read_update_counts: function(feed_id) {
if (feed_id) {
var feed = this.model.get_feed(feed_id);
if (!feed) return;
feed.set('ps', 0);
feed.set('nt', 0);
feed.set('ng', 0);
}
this.model.mark_feed_as_read(feeds, cutoff_timestamp, folder == this.active_folder, _.bind(function() {
if (!this.socket || !this.socket.socket || !this.socket.socket.connected) {
this.force_feeds_refresh(null, false, feeds);
}
}, this));
},
open_story_trainer: function(story_id, feed_id, options) {
@ -4037,6 +4036,13 @@
}
} else if (message == "interaction:new") {
this.update_interactions_count();
} else if (_.string.startsWith(message, "refresh:")) {
var feeds = message.replace('refresh:', '').split(",");
this.force_feeds_refresh(null, false, feeds);
} else if (_.string.startsWith(message, "reload:")) {
if (!NEWSBLUR.reader.flags['reloading_feeds']) {
NEWSBLUR.assets.load_feeds();
}
}
}, this));
@ -4181,6 +4187,12 @@
}, this), Math.random() * delay);
},
feeds_unread_count: function(feed_ids, options) {
options = options || {};
this.model.feed_unread_count(feed_ids, options.callback);
},
update_interactions_count: function() {
this.model.interactions_count(function(data) {
NEWSBLUR.app.sidebar_header.update_interactions_count(data.interactions_count);

View file

@ -217,6 +217,7 @@ NEWSBLUR.ReaderAddFeed = NEWSBLUR.ReaderPopover.extend({
$loading.addClass('NB-active');
$submit.addClass('NB-disabled').text('Adding...');
NEWSBLUR.reader.flags['reloading_feeds'] = true;
this.model.save_add_url(url, folder, $.rescope(this.post_save_add_url, this), $.rescope(this.error, this));
},
@ -225,6 +226,7 @@ NEWSBLUR.ReaderAddFeed = NEWSBLUR.ReaderPopover.extend({
var $submit = this.$('.NB-add-url-submit');
var $loading = this.$('.NB-add-site .NB-loading');
$loading.removeClass('NB-active');
NEWSBLUR.reader.flags['reloading_feeds'] = false;
if (data.code > 0) {
NEWSBLUR.assets.load_feeds(function() {
@ -247,9 +249,11 @@ NEWSBLUR.ReaderAddFeed = NEWSBLUR.ReaderPopover.extend({
error: function(data) {
var $submit = this.$('.NB-add-url-submit');
var $error = this.$('.NB-error');
$(".NB-error-message", $error).text(data.message || "Oh no, there was a problem grabbing that URL and there's no good explanation for what happened.");
$error.slideDown(300);
$submit.text('Add Site');
NEWSBLUR.reader.flags['reloading_feeds'] = false;
},
open_add_folder: function() {

View file

@ -432,8 +432,10 @@ NEWSBLUR.ReaderFeedchooser.prototype = {
var $submit = $('.NB-modal-submit-save', this.$modal);
$submit.addClass('NB-disabled').removeClass('NB-modal-submit-green').val('Saving...');
NEWSBLUR.reader.flags['reloading_feeds'] = true;
this.model.save_feed_chooser(approve_list, function() {
self.flags['has_saved'] = true;
NEWSBLUR.reader.flags['reloading_feeds'] = false;
NEWSBLUR.reader.hide_feed_chooser_button();
NEWSBLUR.assets.load_feeds();
$.modal.close();

View file

@ -210,6 +210,13 @@ NEWSBLUR.utils = {
}
return interval;
},
days_back_to_timestamp: function(days_back) {
days_back = days_back || 0;
var now = Math.round((new Date()).getTime() / 1000);
return now - (days_back * 60*60*24);
}

View file

@ -5,10 +5,10 @@ NEWSBLUR.FeedOptionsPopover = NEWSBLUR.ReaderPopover.extend({
options: {
'width': 264,
'anchor': '.NB-feedbar-options',
'placement': 'bottom right',
'placement': 'bottom -left',
'offset': {
top: 16,
left: -100
top: 18,
left: 0
},
'overlay_top': true,
'popover_class': 'NB-filter-popover-container'
@ -21,16 +21,6 @@ NEWSBLUR.FeedOptionsPopover = NEWSBLUR.ReaderPopover.extend({
},
initialize: function(options) {
if (NEWSBLUR.assets.preference('story_layout') == 'split' &&
NEWSBLUR.assets.preference('story_pane_anchor') == 'south') {
this.options.placement = 'top right';
this.options.offset = {
top: 10,
left: -100
};
this.options.overlay_top = false;
}
this.options = _.extend({}, this.options, options);
NEWSBLUR.ReaderPopover.prototype.initialize.call(this, this.options);
this.model = NEWSBLUR.assets;

View file

@ -8,17 +8,19 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
flags: {},
events: {
"dblclick .feed_counts" : "mark_feed_as_read",
"dblclick" : "open_feed_link",
"click .NB-feedbar-mark-feed-read" : "mark_feed_as_read",
"click .NB-feedbar-train-feed" : "open_trainer",
"click .NB-feedbar-statistics" : "open_statistics",
"click .NB-feedlist-manage-icon" : "show_manage_menu",
"click .NB-feedbar-options" : "open_options_popover",
"click .NB-story-title-indicator" : "show_hidden_story_titles",
"click" : "open",
"mouseenter" : "add_hover_inverse",
"mouseleave" : "remove_hover_inverse"
"dblclick .feed_counts" : "mark_feed_as_read",
"dblclick" : "open_feed_link",
"click .NB-feedbar-mark-feed-read" : "mark_feed_as_read",
"click .NB-feedbar-mark-feed-read-time" : "mark_feed_as_read_days",
"click .NB-feedbar-mark-feed-read-expand" : "expand_mark_read",
"click .NB-feedbar-train-feed" : "open_trainer",
"click .NB-feedbar-statistics" : "open_statistics",
"click .NB-feedlist-manage-icon" : "show_manage_menu",
"click .NB-feedbar-options" : "open_options_popover",
"click .NB-story-title-indicator" : "show_hidden_story_titles",
"click" : "open",
"mouseenter" : "add_hover_inverse",
"mouseleave" : "remove_hover_inverse"
},
initialize: function() {
@ -65,14 +67,8 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
var $feed = $(_.template('<<%= list_type %> class="feed <% if (selected) { %>selected<% } %> <%= extra_classes %> <% if (toplevel) { %>NB-toplevel<% } %>" data-id="<%= feed.id %>">\
<div class="feed_counts">\
</div>\
<img class="feed_favicon" src="<%= $.favicon(feed) %>">\
<span class="feed_title">\
<%= feed.get("feed_title") %>\
<% if (type == "story") { %>\
<div class="NB-feedbar-mark-feed-read"></div>\
<% } %>\
</span>\
<% if (type == "story") { %>\
<div class="NB-search-container"></div>\
<div class="NB-feedbar-options-container">\
<span class="NB-feedbar-options">\
<div class="NB-icon"></div>\
@ -81,12 +77,23 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
<%= NEWSBLUR.assets.view_setting(feed.id, "order") %>\
</span>\
</div>\
<div class="NB-search-container"></div>\
<div class="NB-feedbar-mark-feed-read-container">\
<div class="NB-feedbar-mark-feed-read"><div class="NB-icon"></div></div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="1">1d</div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="3">3d</div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="7">7d</div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="14">14d</div>\
<div class="NB-feedbar-mark-feed-read-expand"></div>\
</div>\
<div class="NB-story-title-indicator">\
<div class="NB-story-title-indicator-count"></div>\
<span class="NB-story-title-indicator-text">show hidden stories</span>\
</div>\
<% } %>\
<img class="feed_favicon" src="<%= $.favicon(feed) %>">\
<span class="feed_title">\
<%= feed.get("feed_title") %>\
</span>\
<div class="NB-feed-exception-icon"></div>\
<div class="NB-feed-unfetched-icon"></div>\
<div class="NB-feedlist-manage-icon"></div>\
@ -282,7 +289,7 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
return false;
},
mark_feed_as_read: function(e) {
mark_feed_as_read: function(e, days) {
if (e) {
e.preventDefault();
e.stopPropagation();
@ -291,13 +298,51 @@ NEWSBLUR.Views.FeedTitleView = Backbone.View.extend({
_.delay(_.bind(function() {
this.flags.double_click = false;
}, this), 500);
NEWSBLUR.reader.mark_feed_as_read(this.model.id);
this.$('.NB-feedbar-mark-feed-read').fadeOut(400);
NEWSBLUR.reader.mark_feed_as_read(this.model.id, days);
this.$('.NB-feedbar-mark-feed-read-container').fadeOut(400);
if (e) {
return false;
}
},
mark_feed_as_read_days: function(e) {
var days = parseInt($(e.target).data('days'), 10);
this.mark_feed_as_read(e, days);
},
expand_mark_read: function() {
var $container = this.$(".NB-feedbar-mark-feed-read-container");
var $markread = this.$(".NB-feedbar-mark-feed-read");
var $hidden = this.$(".NB-story-title-indicator");
var $expand = this.$(".NB-feedbar-mark-feed-read-expand");
var $times = this.$(".NB-feedbar-mark-feed-read-time");
var times_count = $times.length;
$hidden.hide();
$markread.css('z-index', times_count+1);
$container.css('margin-left', $times.eq(0).outerWidth(true) * (times_count - 1) + 12);
$expand.animate({
right: 0,
opacity: 0
}, {
queue: false,
easing: 'easeInQuint',
duration: 180,
complete: function() {
$times.each(function(i) {
$(this).css('z-index', times_count - i);
$(this).animate({
right: (32 * (i + 1)) + 6
}, {
queue: false,
easing: 'easeOutBack',
duration: 280 + 100 * (Math.pow(i, 0.5))
});
});
}
});
},
show_manage_menu_rightclick: function(e) {
if (!NEWSBLUR.assets.preference('show_contextmenus')) return;

View file

@ -12,14 +12,16 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
},
events: {
"click .NB-feedlist-manage-icon" : "show_manage_menu",
"click .folder_title" : "open",
"click .NB-feedlist-collapse-icon" : "collapse_folder",
"click .NB-feedbar-mark-feed-read" : "mark_folder_as_read",
"click .NB-feedbar-options" : "open_options_popover",
"click .NB-story-title-indicator" : "show_hidden_story_titles",
"mouseenter" : "add_hover_inverse",
"mouseleave" : "remove_hover_inverse"
"click .NB-feedlist-manage-icon" : "show_manage_menu",
"click .folder_title" : "open",
"click .NB-feedlist-collapse-icon" : "collapse_folder",
"click .NB-feedbar-mark-feed-read" : "mark_folder_as_read",
"click .NB-feedbar-mark-feed-read-expand" : "expand_mark_read",
"click .NB-feedbar-mark-feed-read-time" : "mark_folder_as_read_days",
"click .NB-feedbar-options" : "open_options_popover",
"click .NB-story-title-indicator" : "show_hidden_story_titles",
"mouseenter" : "add_hover_inverse",
"mouseleave" : "remove_hover_inverse"
},
initialize: function() {
@ -102,14 +104,8 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
var $folder = _.template('<<%= list_type %> class="folder NB-folder">\
<% if (!root) { %>\
<div class="folder_title <% if (depth <= 1) { %>NB-toplevel<% } %>">\
<div class="NB-folder-icon"></div>\
<div class="NB-feedlist-collapse-icon" title="<% if (is_collapsed) { %>Expand Folder<% } else {%>Collapse Folder<% } %>"></div>\
<div class="NB-feedlist-manage-icon"></div>\
<span class="folder_title_text">\
<span><%= folder_title %></span>\
<div class="NB-feedbar-mark-feed-read"></div>\
</span>\
<% if (feedbar) { %>\
<div class="NB-search-container"></div>\
<div class="NB-feedbar-options-container">\
<span class="NB-feedbar-options">\
<div class="NB-icon"></div>\
@ -118,12 +114,25 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
<%= NEWSBLUR.assets.view_setting("river:"+folder_title, "order") %>\
</span>\
</div>\
<div class="NB-search-container"></div>\
<div class="NB-feedbar-mark-feed-read-container">\
<div class="NB-feedbar-mark-feed-read"><div class="NB-icon"></div></div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="1">1d</div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="3">3d</div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="7">7d</div>\
<div class="NB-feedbar-mark-feed-read-time" data-days="14">14d</div>\
<div class="NB-feedbar-mark-feed-read-expand"></div>\
</div>\
<div class="NB-story-title-indicator">\
<div class="NB-story-title-indicator-count"></div>\
<span class="NB-story-title-indicator-text">show hidden stories</span>\
</div>\
<% } %>\
<% } %>\
<div class="NB-folder-icon"></div>\
<div class="NB-feedlist-collapse-icon" title="<% if (is_collapsed) { %>Expand Folder<% } else {%>Collapse Folder<% } %>"></div>\
<div class="NB-feedlist-manage-icon"></div>\
<span class="folder_title_text">\
<span><%= folder_title %></span>\
</span>\
</div>\
<% } %>\
<% if (!feedbar) { %>\
@ -350,9 +359,18 @@ NEWSBLUR.Views.Folder = Backbone.View.extend({
}
},
mark_folder_as_read: function() {
NEWSBLUR.reader.mark_folder_as_read();
this.$('.NB-feedbar-mark-feed-read').fadeOut(400);
mark_folder_as_read: function(e, days_back) {
NEWSBLUR.reader.mark_folder_as_read(this.model, days_back);
this.$('.NB-feedbar-mark-feed-read-container').fadeOut(400);
},
mark_folder_as_read_days: function(e) {
var days = parseInt($(e.target).data('days'), 10);
this.mark_folder_as_read(e, days);
},
expand_mark_read: function() {
NEWSBLUR.Views.FeedTitleView.prototype.expand_mark_read.call(this);
},
open_options_popover: function() {

View file

@ -51,13 +51,13 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
if (!_.contains(['split', 'full'], NEWSBLUR.assets.preference('story_layout'))) return;
var collection = this.collection;
var stories = this.collection.map(function(story) {
if (story.story_view) return;
var stories = _.compact(this.collection.map(function(story) {
// if (story.story_view) return story;
return new NEWSBLUR.Views.StoryDetailView({
model: story,
collection: collection
}).render();
});
}));
if (NEWSBLUR.assets.preference('feed_view_single_story')) {
this.show_correct_explainer();
@ -621,7 +621,7 @@ NEWSBLUR.Views.StoryListView = Backbone.View.extend({
var story_view = NEWSBLUR.reader.story_view;
var offset = this.cache.offset || 0;
if (NEWSBLUR.assets.preference('story_layout') == 'full' && !this.cache.offset) {
offset = this.cache.offset = $(".NB-feed-story-view-header").outerHeight();
// offset = this.cache.offset = $(".NB-feed-story-view-header").outerHeight();
}
if ((story_view == 'feed' ||

View file

@ -16,15 +16,15 @@ NEWSBLUR.Views.StoryTitlesHeader = Backbone.View.extend({
this.showing_fake_folder = NEWSBLUR.reader.flags['river_view'] &&
NEWSBLUR.reader.active_folder &&
(NEWSBLUR.reader.active_folder.get('fake') || !NEWSBLUR.reader.active_folder.get('folder_title'));
if (this.options.layout == 'split' || this.options.layout == 'list') {
// if (this.options.layout == 'split' || this.options.layout == 'list') {
this.$story_titles_feedbar.show();
this.$feed_view_feedbar.hide();
this.setElement(this.$story_titles_feedbar);
} else if (this.options.layout == 'full') {
this.$story_titles_feedbar.hide();
this.$feed_view_feedbar.show();
this.setElement(this.$feed_view_feedbar);
}
// } else if (this.options.layout == 'full') {
// this.$story_titles_feedbar.hide();
// this.$feed_view_feedbar.show();
// this.setElement(this.$feed_view_feedbar);
// }
},
render: function() {
@ -44,13 +44,10 @@ NEWSBLUR.Views.StoryTitlesHeader = Backbone.View.extend({
feedbar_view: this
}).render();
this.search_view.blur_search();
$view.append(this.search_view.$el);
$view.prepend(this.search_view.$el);
} else if (this.showing_fake_folder) {
$view = $(_.template('\
<div class="NB-folder NB-no-hover">\
<div class="NB-folder-icon"></div>\
<div class="NB-feedlist-manage-icon"></div>\
<span class="folder_title_text"><%= folder_title %></span>\
<% if (show_options) { %>\
<div class="NB-feedbar-options-container">\
<span class="NB-feedbar-options">\
@ -65,6 +62,9 @@ NEWSBLUR.Views.StoryTitlesHeader = Backbone.View.extend({
<div class="NB-story-title-indicator-count"></div>\
<span class="NB-story-title-indicator-text">show hidden stories</span>\
</div>\
<div class="NB-folder-icon"></div>\
<div class="NB-feedlist-manage-icon"></div>\
<span class="folder_title_text"><%= folder_title %></span>\
</div>\
', {
folder_title: this.fake_folder_title(),

View file

@ -4,7 +4,7 @@
{% block body %}
<p style="font-size: 37px; color:#555555; margin-top: 18px;margin-bottom: 10px;padding-top:6px;">Welcome to NewsBlur, {{ user.username }}.</p>
<p style="line-height: 20px;">Thanks for trying out NewsBlur! I hope Newsblur can make your daily reading more personal, sociable, and pleasurable.</p>
<p style="line-height: 20px;">Thanks for trying out NewsBlur! I hope NewsBlur can make your daily reading more personal, sociable, and pleasurable.</p>
<p style="line-height: 20px;">Here are some ways to make NewsBlur work for you:</p>
<p style="line-height: 20px;">
<ul style="list-style: none;">

View file

@ -161,7 +161,26 @@
<div class="right-pane">
<div id="story_taskbar" class="NB-taskbar-container content-north">
<div class="NB-feedbar content-north">
<ul class="segmented-control NB-taskbar NB-taskbar-nav">
<li class="NB-taskbar-button NB-task-story-previous">
<div class="NB-task-image"></div>
</li>
<li class="NB-taskbar-button NB-task-story-next-unread NB-task-story-next-positive">
<div class="NB-task-image"></div>
<span class="NB-task-title">Next Unread</span>
</li>
<li class="NB-taskbar-button NB-task-story-next">
<div class="NB-task-image"></div>
</li>
</ul>
<div class="NB-story-titles-header"></div>
</div>
<div id="story_taskbar" class="NB-taskbar-container content-south">
<ul class="segmented-control NB-taskbar NB-taskbar-view">
<li class="NB-taskbar-button task_view_page NB-tipsy" tipsy-title="Original">
<div class="NB-task-image"></div>
@ -188,19 +207,6 @@
</li>
</ul>
<ul class="segmented-control NB-taskbar NB-taskbar-nav">
<li class="NB-taskbar-button NB-task-story-previous">
<div class="NB-task-image"></div>
</li>
<li class="NB-taskbar-button NB-task-story-next-unread NB-task-story-next-positive">
<div class="NB-task-image"></div>
<span class="NB-task-title">Next Unread</span>
</li>
<li class="NB-taskbar-button NB-task-story-next">
<div class="NB-task-image"></div>
</li>
</ul>
<ul class="segmented-control NB-taskbar NB-taskbar-layout">
<li class="NB-taskbar-button NB-task-layout-full NB-tipsy" tipsy-title="Full">
<div class="NB-task-image"></div>
@ -226,9 +232,8 @@
</div>
<div class="content-pane">
<div id="story_titles" class="right-north">
<div class="NB-story-titles-header NB-feedbar"></div>
<div class="NB-story-titles"></div>
</div>

View file

@ -435,8 +435,6 @@ class Dispatcher:
feed_code = 500
elif ret_feed == FEED_ERRPARSE:
feed_code = 550
elif ret_feed == FEED_ERRPARSE:
feed_code = 550
if not feed: continue
feed = self.refresh_feed(feed.pk)