diff --git a/clients/ios/Classes/FeedDetailTableCell.h b/clients/ios/Classes/FeedDetailTableCell.h index cf8edb44b..f48a0641e 100644 --- a/clients/ios/Classes/FeedDetailTableCell.h +++ b/clients/ios/Classes/FeedDetailTableCell.h @@ -8,9 +8,9 @@ #import #import "NewsBlurAppDelegate.h" -#import "ABTableViewCell.h" +#import "MCSwipeTableViewCell.h" -@interface FeedDetailTableCell : ABTableViewCell { +@interface FeedDetailTableCell : MCSwipeTableViewCell { NewsBlurAppDelegate *appDelegate; // All views @@ -53,5 +53,12 @@ @property (readwrite) BOOL hasAlpha; - (UIImage *)imageByApplyingAlpha:(UIImage *)image withAlpha:(CGFloat) alpha; - +- (void)setupGestures; + @end + +@interface FeedDetailTableCellView : UIView + +@property (nonatomic) FeedDetailTableCell *cell; + +@end \ No newline at end of file diff --git a/clients/ios/Classes/FeedDetailTableCell.m b/clients/ios/Classes/FeedDetailTableCell.m index 6b5859ae3..62db7c3c4 100644 --- a/clients/ios/Classes/FeedDetailTableCell.m +++ b/clients/ios/Classes/FeedDetailTableCell.m @@ -11,10 +11,12 @@ #import "ABTableViewCell.h" #import "UIView+TKCategory.h" #import "Utilities.h" +#import "MCSwipeTableViewCell.h" static UIFont *textFont = nil; static UIFont *indicatorFont = nil; +@class FeedDetailViewController; @implementation FeedDetailTableCell @@ -45,216 +47,6 @@ static UIFont *indicatorFont = nil; } } -- (void)drawContentView:(CGRect)r highlighted:(BOOL)highlighted { - - - int adjustForSocial = 3; - if (self.isRiverOrSocial) { - adjustForSocial = 20; - } - - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGRect rect = CGRectInset(r, 12, 12); - rect.size.width -= 18; // Scrollbar padding - - UIColor *backgroundColor; - backgroundColor = highlighted ? UIColorFromRGB(0xFFFDEF) : UIColorFromRGB(0xf4f4f4); - [backgroundColor set]; - - CGContextFillRect(context, r); - - if (highlighted) { -// [NewsBlurAppDelegate fillGradient:r startColor:UIColorFromRGB(0xFFFDEF) endColor:UIColorFromRGB(0xFFFDDF)]; - } - - UIColor *textColor; - UIFont *font; - - if (self.isRead) { - font = [UIFont fontWithName:@"Helvetica" size:11]; - textColor = UIColorFromRGB(0x808080); - } else { - font = [UIFont fontWithName:@"Helvetica-Bold" size:11]; - textColor = UIColorFromRGB(0x606060); - - } - if (highlighted) { - textColor = UIColorFromRGB(0x686868); - } - - NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; - paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; - paragraphStyle.alignment = NSTextAlignmentLeft; - - if (self.isRiverOrSocial) { - [self.siteTitle drawInRect:CGRectMake(leftMargin + 20, 7, rect.size.width - 20, 21) - withAttributes:@{NSFontAttributeName: font, - NSForegroundColorAttributeName: textColor, - NSParagraphStyleAttributeName: paragraphStyle}]; - - if (self.isRead) { - font = [UIFont fontWithName:@"Helvetica" size:12]; - textColor = UIColorFromRGB(0x606060); - - } else { - textColor = UIColorFromRGB(0x333333); - font = [UIFont fontWithName:@"Helvetica-Bold" size:12]; - } - if (highlighted) { - textColor = UIColorFromRGB(0x686868); - } - } - - // story title - CGSize theSize = [self.storyTitle - boundingRectWithSize:CGSizeMake(rect.size.width, 30.0) - options:nil - attributes:@{NSFontAttributeName: font, - NSParagraphStyleAttributeName: paragraphStyle} - context:nil].size; - - int storyTitleY = 7 + adjustForSocial + ((30 - theSize.height)/2); - if (self.isShort) { - storyTitleY = 7 + adjustForSocial + 2; - } - int storyTitleX = leftMargin; - if (self.isStarred) { - UIImage *savedIcon = [UIImage imageNamed:@"clock"]; - [savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1]; - storyTitleX += 20; - } - if (self.isShared) { - UIImage *savedIcon = [UIImage imageNamed:@"menu_icn_share"]; - [savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1]; - storyTitleX += 20; - } - [self.storyTitle drawInRect:CGRectMake(storyTitleX, storyTitleY, rect.size.width - storyTitleX + leftMargin, theSize.height) - withAttributes:@{NSFontAttributeName: font, - NSForegroundColorAttributeName: textColor, - NSParagraphStyleAttributeName: paragraphStyle}]; - - int storyAuthorDateY = 41 + adjustForSocial; - if (self.isShort) { - storyAuthorDateY -= 13; - } - - // story author style - if (self.isRead) { - textColor = UIColorFromRGB(0x959595); - font = [UIFont fontWithName:@"Helvetica" size:10]; - } else { - textColor = UIColorFromRGB(0xA6A8A2); - font = [UIFont fontWithName:@"Helvetica-Bold" size:10]; - } - if (highlighted) { - textColor = UIColorFromRGB(0x686868); - } - - [self.storyAuthor - drawInRect:CGRectMake(leftMargin, storyAuthorDateY, (rect.size.width) / 2 - 10, 15.0) - withAttributes:@{NSFontAttributeName: font, - NSForegroundColorAttributeName: textColor, - NSParagraphStyleAttributeName: paragraphStyle}]; - // story date - if (self.isRead) { - textColor = UIColorFromRGB(0xbabdd1); - font = [UIFont fontWithName:@"Helvetica" size:10]; - } else { - textColor = UIColorFromRGB(0x262c6c); - font = [UIFont fontWithName:@"Helvetica-Bold" size:10]; - } - - if (highlighted) { - textColor = UIColorFromRGB(0x686868); - } - - paragraphStyle.alignment = NSTextAlignmentRight; - [self.storyDate - drawInRect:CGRectMake(leftMargin + (rect.size.width) / 2 - 10, storyAuthorDateY, (rect.size.width) / 2 + 10, 15.0) - withAttributes:@{NSFontAttributeName: font, - NSForegroundColorAttributeName: textColor, - NSParagraphStyleAttributeName: paragraphStyle}]; - // feed bar - - CGContextSetStrokeColor(context, CGColorGetComponents([self.feedColorBarTopBorder CGColor])); - if (self.isRead) { - CGContextSetAlpha(context, 0.15); - } - CGContextSetLineWidth(context, 4.0f); - CGContextBeginPath(context); - CGContextMoveToPoint(context, 2.0f, 1.0f); - CGContextAddLineToPoint(context, 2.0f, self.frame.size.height - 1); - CGContextStrokePath(context); - - CGContextSetStrokeColor(context, CGColorGetComponents([self.feedColorBar CGColor])); - CGContextBeginPath(context); - CGContextMoveToPoint(context, 6.0f, 1.0f); - CGContextAddLineToPoint(context, 6.0, self.frame.size.height - 1); - CGContextStrokePath(context); - - // reset for borders - - CGContextSetAlpha(context, 1.0); - CGContextSetLineWidth(context, 1.0f); - if (highlighted) { - // top border - UIColor *blue = UIColorFromRGB(0xF9F8F4); - - CGContextSetStrokeColor(context, CGColorGetComponents([blue CGColor])); - - CGContextBeginPath(context); - CGContextMoveToPoint(context, 0, 0.5f); - CGContextAddLineToPoint(context, self.bounds.size.width, 0.5f); - CGContextStrokePath(context); - - // bottom border - CGContextBeginPath(context); - CGContextMoveToPoint(context, 0, self.bounds.size.height - 1.5f); - CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height - 1.5f); - CGContextStrokePath(context); - } else { - // top border - UIColor *white = UIColorFromRGB(0xffffff); - - CGContextSetStrokeColor(context, CGColorGetComponents([white CGColor])); - - CGContextBeginPath(context); - CGContextMoveToPoint(context, 0.0f, 0.5f); - CGContextAddLineToPoint(context, self.bounds.size.width, 0.5f); - CGContextStrokePath(context); - } - - // site favicon - if (self.isRead && !self.hasAlpha) { - if (self.isRiverOrSocial) { - self.siteFavicon = [self imageByApplyingAlpha:self.siteFavicon withAlpha:0.25]; - } - self.hasAlpha = YES; - } - - if (self.isRiverOrSocial) { - [self.siteFavicon drawInRect:CGRectMake(leftMargin, 6.0, 16.0, 16.0)]; - } - - // story indicator - int storyIndicatorY = 4 + adjustForSocial; - if (self.isShort){ - storyIndicatorY = 4 + adjustForSocial - 5 ; - } - - UIImage *unreadIcon; - if (storyScore == -1) { - unreadIcon = [UIImage imageNamed:@"g_icn_hidden"]; - } else if (storyScore == 1) { - unreadIcon = [UIImage imageNamed:@"g_icn_focus"]; - } else { - unreadIcon = [UIImage imageNamed:@"g_icn_unread"]; - } - - [unreadIcon drawInRect:CGRectMake(15, storyIndicatorY + 14, 8, 8) blendMode:nil alpha:(self.isRead ? .15 : 1)]; -} - - (UIImage *)imageByApplyingAlpha:(UIImage *)image withAlpha:(CGFloat) alpha { UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0f); @@ -277,5 +69,277 @@ static UIFont *indicatorFont = nil; return newImage; } +- (void)setupGestures { + NSString *unreadIcon; + if (storyScore == -1) { + unreadIcon = @"g_icn_hidden.png"; + } else if (storyScore == 1) { + unreadIcon = @"g_icn_focus.png"; + } else { + unreadIcon = @"g_icn_unread.png"; + } + + appDelegate = [NewsBlurAppDelegate sharedAppDelegate]; + [self setDelegate:appDelegate.feedDetailViewController]; + [self setFirstStateIconName:@"clock.png" + firstColor:[UIColor colorWithRed:85.0 / 255.0 green:213.0 / 255.0 blue:80.0 / 255.0 alpha:1.0] + secondStateIconName:nil + secondColor:nil + thirdIconName:unreadIcon + thirdColor:[UIColor colorWithRed:254.0 / 255.0 green:217.0 / 255.0 blue:56.0 / 255.0 alpha:1.0] + fourthIconName:nil + fourthColor:nil]; + +// [self.contentView setBackgroundColor:[UIColor whiteColor]]; + + // Setting the default inactive state color to the tableView background color +// [self setDefaultColor:self.tableView.backgroundView.backgroundColor]; + + // + [self setSelectionStyle:UITableViewCellSelectionStyleGray]; + + self.mode = MCSwipeTableViewCellModeSwitch; + self.shouldAnimatesIcons = NO; +} + +- (void)setNeedsDisplay { + [super setNeedsDisplay]; + for (UIView *view in self.contentView.subviews) { + [view setNeedsDisplay]; + } +} + +- (void)setNeedsLayout { + [super setNeedsLayout]; + for (UIView *view in self.contentView.subviews) { + [view setNeedsLayout]; + } +} + +- (void) setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:NO]; + + if (animated) { + [CATransaction begin]; + CATransition* animation = [CATransition animation]; + animation.type = kCATransitionFade; + animation.duration = 0.6; + [animation setTimingFunction:[CAMediaTimingFunction + functionWithName:kCAMediaTimingFunctionDefault]]; + [self.contentView.layer addAnimation:animation forKey:@"deselectRow"]; + [CATransaction commit]; + } +} @end + +@implementation FeedDetailTableCellView + +@synthesize cell; + +- (void)drawRect:(CGRect)r { + int adjustForSocial = 3; + if (cell.isRiverOrSocial) { + adjustForSocial = 20; + } + + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGRect rect = CGRectInset(r, 12, 12); + rect.size.width -= 18; // Scrollbar padding + + UIColor *backgroundColor; + backgroundColor = cell.highlighted || cell.selected ? + UIColorFromRGB(0xFFFDEF) : UIColorFromRGB(0xf4f4f4); + [backgroundColor set]; + + CGContextFillRect(context, r); + + UIColor *textColor; + UIFont *font; + + if (cell.isRead) { + font = [UIFont fontWithName:@"Helvetica" size:11]; + textColor = UIColorFromRGB(0x808080); + } else { + font = [UIFont fontWithName:@"Helvetica-Bold" size:11]; + textColor = UIColorFromRGB(0x606060); + + } + if (cell.highlighted || cell.selected) { + textColor = UIColorFromRGB(0x686868); + } + + NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; + paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; + paragraphStyle.alignment = NSTextAlignmentLeft; + + if (cell.isRiverOrSocial) { + [cell.siteTitle drawInRect:CGRectMake(leftMargin + 20, 7, rect.size.width - 20, 21) + withAttributes:@{NSFontAttributeName: font, + NSForegroundColorAttributeName: textColor, + NSParagraphStyleAttributeName: paragraphStyle}]; + + if (cell.isRead) { + font = [UIFont fontWithName:@"Helvetica" size:12]; + textColor = UIColorFromRGB(0x606060); + + } else { + textColor = UIColorFromRGB(0x333333); + font = [UIFont fontWithName:@"Helvetica-Bold" size:12]; + } + if (cell.highlighted || cell.selected) { + textColor = UIColorFromRGB(0x686868); + } + } + + // story title + CGSize theSize = [cell.storyTitle + boundingRectWithSize:CGSizeMake(rect.size.width, 30.0) + options:nil + attributes:@{NSFontAttributeName: font, + NSParagraphStyleAttributeName: paragraphStyle} + context:nil].size; + + int storyTitleY = 7 + adjustForSocial + ((30 - theSize.height)/2); + if (cell.isShort) { + storyTitleY = 7 + adjustForSocial + 2; + } + int storyTitleX = leftMargin; + if (cell.isStarred) { + UIImage *savedIcon = [UIImage imageNamed:@"clock"]; + [savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1]; + storyTitleX += 20; + } + if (cell.isShared) { + UIImage *savedIcon = [UIImage imageNamed:@"menu_icn_share"]; + [savedIcon drawInRect:CGRectMake(storyTitleX, storyTitleY - 1, 16, 16) blendMode:nil alpha:1]; + storyTitleX += 20; + } + [cell.storyTitle drawInRect:CGRectMake(storyTitleX, storyTitleY, rect.size.width - storyTitleX + leftMargin, theSize.height) + withAttributes:@{NSFontAttributeName: font, + NSForegroundColorAttributeName: textColor, + NSParagraphStyleAttributeName: paragraphStyle}]; + + int storyAuthorDateY = 41 + adjustForSocial; + if (cell.isShort) { + storyAuthorDateY -= 13; + } + + // story author style + if (cell.isRead) { + textColor = UIColorFromRGB(0x959595); + font = [UIFont fontWithName:@"Helvetica" size:10]; + } else { + textColor = UIColorFromRGB(0xA6A8A2); + font = [UIFont fontWithName:@"Helvetica-Bold" size:10]; + } + if (cell.highlighted || cell.selected) { + textColor = UIColorFromRGB(0x686868); + } + + [cell.storyAuthor + drawInRect:CGRectMake(leftMargin, storyAuthorDateY, (rect.size.width) / 2 - 10, 15.0) + withAttributes:@{NSFontAttributeName: font, + NSForegroundColorAttributeName: textColor, + NSParagraphStyleAttributeName: paragraphStyle}]; + // story date + if (cell.isRead) { + textColor = UIColorFromRGB(0xbabdd1); + font = [UIFont fontWithName:@"Helvetica" size:10]; + } else { + textColor = UIColorFromRGB(0x262c6c); + font = [UIFont fontWithName:@"Helvetica-Bold" size:10]; + } + + if (cell.highlighted || cell.selected) { + textColor = UIColorFromRGB(0x686868); + } + + paragraphStyle.alignment = NSTextAlignmentRight; + [cell.storyDate + drawInRect:CGRectMake(leftMargin + (rect.size.width) / 2 - 10, storyAuthorDateY, (rect.size.width) / 2 + 10, 15.0) + withAttributes:@{NSFontAttributeName: font, + NSForegroundColorAttributeName: textColor, + NSParagraphStyleAttributeName: paragraphStyle}]; + // feed bar + + CGContextSetStrokeColor(context, CGColorGetComponents([cell.feedColorBarTopBorder CGColor])); + if (cell.isRead) { + CGContextSetAlpha(context, 0.15); + } + CGContextSetLineWidth(context, 4.0f); + CGContextBeginPath(context); + CGContextMoveToPoint(context, 2.0f, 1.0f); + CGContextAddLineToPoint(context, 2.0f, cell.frame.size.height - 1); + CGContextStrokePath(context); + + CGContextSetStrokeColor(context, CGColorGetComponents([cell.feedColorBar CGColor])); + CGContextBeginPath(context); + CGContextMoveToPoint(context, 6.0f, 1.0f); + CGContextAddLineToPoint(context, 6.0, cell.frame.size.height - 1); + CGContextStrokePath(context); + + // reset for borders + + CGContextSetAlpha(context, 1.0); + CGContextSetLineWidth(context, 1.0f); + if (cell.highlighted || cell.selected) { + // top border + UIColor *blue = UIColorFromRGB(0xF9F8F4); + + CGContextSetStrokeColor(context, CGColorGetComponents([blue CGColor])); + + CGContextBeginPath(context); + CGContextMoveToPoint(context, 0, 0.5f); + CGContextAddLineToPoint(context, cell.bounds.size.width, 0.5f); + CGContextStrokePath(context); + + // bottom border + CGContextBeginPath(context); + CGContextMoveToPoint(context, 0, cell.bounds.size.height - .5f); + CGContextAddLineToPoint(context, cell.bounds.size.width, cell.bounds.size.height - .5f); + CGContextStrokePath(context); + } else { + // top border + UIColor *white = UIColorFromRGB(0xffffff); + + CGContextSetStrokeColor(context, CGColorGetComponents([white CGColor])); + + CGContextBeginPath(context); + CGContextMoveToPoint(context, 0.0f, 0.5f); + CGContextAddLineToPoint(context, cell.bounds.size.width, 0.5f); + CGContextStrokePath(context); + } + + // site favicon + if (cell.isRead && !cell.hasAlpha) { + if (cell.isRiverOrSocial) { + cell.siteFavicon = [cell imageByApplyingAlpha:cell.siteFavicon withAlpha:0.25]; + } + cell.hasAlpha = YES; + } + + if (cell.isRiverOrSocial) { + [cell.siteFavicon drawInRect:CGRectMake(leftMargin, 6.0, 16.0, 16.0)]; + } + + // story indicator + int storyIndicatorY = 4 + adjustForSocial; + if (cell.isShort){ + storyIndicatorY = 4 + adjustForSocial - 5 ; + } + + UIImage *unreadIcon; + if (cell.storyScore == -1) { + unreadIcon = [UIImage imageNamed:@"g_icn_hidden"]; + } else if (cell.storyScore == 1) { + unreadIcon = [UIImage imageNamed:@"g_icn_focus"]; + } else { + unreadIcon = [UIImage imageNamed:@"g_icn_unread"]; + } + + [unreadIcon drawInRect:CGRectMake(15, storyIndicatorY + 14, 8, 8) blendMode:nil alpha:(cell.isRead ? .15 : 1)]; +} + +@end \ No newline at end of file diff --git a/clients/ios/Classes/FeedDetailViewController.h b/clients/ios/Classes/FeedDetailViewController.h index e80e2b104..dc256b11f 100644 --- a/clients/ios/Classes/FeedDetailViewController.h +++ b/clients/ios/Classes/FeedDetailViewController.h @@ -14,15 +14,17 @@ #import "WEPopoverController.h" #import "TransparentToolbar.h" #import "NBNotifier.h" +#import "MCSwipeTableViewCell.h" @class NewsBlurAppDelegate; @class FeedDetailTableCell; +@class MCSwipeTableViewCell; @interface FeedDetailViewController : BaseViewController { + WEPopoverControllerDelegate, MCSwipeTableViewCellDelegate> { NewsBlurAppDelegate *appDelegate; int feedPage; diff --git a/clients/ios/Classes/FeedDetailViewController.m b/clients/ios/Classes/FeedDetailViewController.m index 02279998f..0105d9109 100644 --- a/clients/ios/Classes/FeedDetailViewController.m +++ b/clients/ios/Classes/FeedDetailViewController.m @@ -852,23 +852,23 @@ NSString *cellIdentifier; NSDictionary *feed ; + if (indexPath.row >= appDelegate.storyLocationsCount) { + return [self makeLoadingCell]; + } + if (appDelegate.isRiverView || appDelegate.isSocialView) { cellIdentifier = @"FeedRiverDetailCellIdentifier"; } else { cellIdentifier = @"FeedDetailCellIdentifier"; } - FeedDetailTableCell *cell = (FeedDetailTableCell *)[tableView - dequeueReusableCellWithIdentifier:cellIdentifier]; + FeedDetailTableCell *cell = (FeedDetailTableCell *)[tableView + dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[FeedDetailTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; } - - if (indexPath.row >= appDelegate.storyLocationsCount) { - return [self makeLoadingCell]; - } - + NSDictionary *story = [self getStoryAtRow:indexPath.row]; id feedId = [story objectForKey:@"story_feed_id"]; @@ -951,14 +951,21 @@ cell.isRiverOrSocial = YES; } - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { NSInteger rowIndex = [appDelegate locationOfActiveStory]; if (rowIndex == indexPath.row) { [self.storyTitlesTable selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; } } + + FeedDetailTableCellView *content = [[FeedDetailTableCellView alloc] + initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, [self tableView:self.storyTitlesTable heightForRowAtIndexPath:indexPath])]; + content.cell = cell; + [cell.contentView addSubview:content]; + [content sizeToFit]; + [cell setupGestures]; - return cell; + return cell; } - (void)loadStory:(FeedDetailTableCell *)cell atRow:(NSInteger)row { @@ -1076,6 +1083,29 @@ return [appDelegate.activeFeedStories objectAtIndex:row]; } + +#pragma mark - MCSwipeTableViewCellDelegate + +// When the user starts swiping the cell this method is called +- (void)swipeTableViewCellDidStartSwiping:(MCSwipeTableViewCell *)cell { + NSLog(@"Did start swiping the cell!"); +} + +/* + // When the user is dragging, this method is called and return the dragged percentage from the border + - (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didSwipWithPercentage:(CGFloat)percentage { + NSLog(@"Did swipe with percentage : %f", percentage); + } + */ + +- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state mode:(MCSwipeTableViewCellMode)mode { + NSLog(@"Did end swipping with IndexPath : %@ - MCSwipeTableViewCellState : %d - MCSwipeTableViewCellMode : %d", [self.storyTitlesTable indexPathForCell:cell], state, mode); + + if (mode == MCSwipeTableViewCellModeExit) { + [self.storyTitlesTable deleteRowsAtIndexPaths:@[[self.storyTitlesTable indexPathForCell:cell]] withRowAnimation:UITableViewRowAnimationFade]; + } +} + #pragma mark - #pragma mark Feed Actions diff --git a/clients/ios/NewsBlur.xcodeproj/project.pbxproj b/clients/ios/NewsBlur.xcodeproj/project.pbxproj index 5e7e3f15b..f46eba70e 100755 --- a/clients/ios/NewsBlur.xcodeproj/project.pbxproj +++ b/clients/ios/NewsBlur.xcodeproj/project.pbxproj @@ -350,6 +350,7 @@ FFCDD8F717F4BCB4000C6483 /* Default-portrait@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FFCDD8F117F4BCB4000C6483 /* Default-portrait@2x.png */; }; FFCDD8F817F4BCB4000C6483 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = FFCDD8F217F4BCB4000C6483 /* Default.png */; }; FFCDD8FA17F50C08000C6483 /* drag_icon.png in Resources */ = {isa = PBXBuildFile; fileRef = FFCDD8F917F50C08000C6483 /* drag_icon.png */; }; + FFCDD8FE17F6368F000C6483 /* MCSwipeTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFCDD8FD17F6368F000C6483 /* MCSwipeTableViewCell.m */; }; FFD1D7311459B63500E46F89 /* BaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD1D7301459B63500E46F89 /* BaseViewController.m */; }; FFD887F01445F1E800385399 /* AddSiteAutocompleteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFD887EE1445F1E800385399 /* AddSiteAutocompleteCell.m */; }; FFDCA0AF16E80866000D8E0C /* DEComposeRuledView.m in Sources */ = {isa = PBXBuildFile; fileRef = FFDCA0A516E80866000D8E0C /* DEComposeRuledView.m */; }; @@ -917,6 +918,8 @@ FFCDD8F117F4BCB4000C6483 /* Default-portrait@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-portrait@2x.png"; sourceTree = ""; }; FFCDD8F217F4BCB4000C6483 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; FFCDD8F917F50C08000C6483 /* drag_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = drag_icon.png; sourceTree = ""; }; + FFCDD8FC17F6368F000C6483 /* MCSwipeTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCSwipeTableViewCell.h; sourceTree = ""; }; + FFCDD8FD17F6368F000C6483 /* MCSwipeTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCSwipeTableViewCell.m; sourceTree = ""; }; FFD1D72F1459B63500E46F89 /* BaseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseViewController.h; sourceTree = ""; }; FFD1D7301459B63500E46F89 /* BaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseViewController.m; sourceTree = ""; }; FFD887ED1445F1E800385399 /* AddSiteAutocompleteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddSiteAutocompleteCell.h; sourceTree = ""; }; @@ -1091,6 +1094,7 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( + FFCDD8FB17F6368F000C6483 /* MCSwipeTableViewCell */, FF5D40091799F70200349659 /* ARChromeActivity */, FFAF53951799E69D00C7FCCB /* PocketSDK */, FFAF53A61799E69D00C7FCCB /* ReadabilityActivity */, @@ -1943,6 +1947,16 @@ path = logos; sourceTree = ""; }; + FFCDD8FB17F6368F000C6483 /* MCSwipeTableViewCell */ = { + isa = PBXGroup; + children = ( + FFCDD8FC17F6368F000C6483 /* MCSwipeTableViewCell.h */, + FFCDD8FD17F6368F000C6483 /* MCSwipeTableViewCell.m */, + ); + name = MCSwipeTableViewCell; + path = "Other Sources/MCSwipeTableViewCell"; + sourceTree = ""; + }; FFDCA0A316E80866000D8E0C /* REComposeViewController */ = { isa = PBXGroup; children = ( @@ -2400,6 +2414,7 @@ 78095E35128EF30D00230C8E /* ASIDownloadCache.m in Sources */, 78095E36128EF30D00230C8E /* ASIFormDataRequest.m in Sources */, 78095E37128EF30D00230C8E /* ASIHTTPRequest.m in Sources */, + FFCDD8FE17F6368F000C6483 /* MCSwipeTableViewCell.m in Sources */, 78095E38128EF30D00230C8E /* ASIInputStream.m in Sources */, 78095E39128EF30D00230C8E /* ASINetworkQueue.m in Sources */, 78095EC9128F30B500230C8E /* OriginalStoryViewController.m in Sources */, diff --git a/clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.h b/clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.h new file mode 100755 index 000000000..27cecced6 --- /dev/null +++ b/clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.h @@ -0,0 +1,99 @@ +// +// MCSwipeTableViewCell.h +// MCSwipeTableViewCell +// +// Created by Ali Karagoz on 24/02/13. +// Copyright (c) 2013 Mad Castle. All rights reserved. +// + +#import + +@class MCSwipeTableViewCell; + +typedef NS_ENUM(NSUInteger, MCSwipeTableViewCellState){ + MCSwipeTableViewCellStateNone = 0, + MCSwipeTableViewCellState1, + MCSwipeTableViewCellState2, + MCSwipeTableViewCellState3, + MCSwipeTableViewCellState4 +}; + +typedef NS_ENUM(NSUInteger, MCSwipeTableViewCellDirection){ + MCSwipeTableViewCellDirectionLeft = 0, + MCSwipeTableViewCellDirectionCenter, + MCSwipeTableViewCellDirectionRight +}; + +typedef NS_ENUM(NSUInteger, MCSwipeTableViewCellMode){ + MCSwipeTableViewCellModeNone = 0, + MCSwipeTableViewCellModeExit, + MCSwipeTableViewCellModeSwitch +}; + +@protocol MCSwipeTableViewCellDelegate + +@optional + +// When the user starts swiping the cell this method is called +- (void)swipeTableViewCellDidStartSwiping:(MCSwipeTableViewCell *)cell; + +// When the user is dragging, this method is called and return the dragged percentage from the border +- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didSwipWithPercentage:(CGFloat)percentage; + +// When the user releases the cell, after swiping it, this method is called +- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state mode:(MCSwipeTableViewCellMode)mode; + +@end + +@interface MCSwipeTableViewCell : UITableViewCell + +@property (nonatomic, assign) id delegate; + +@property (nonatomic, copy) NSString *firstIconName; +@property (nonatomic, copy) NSString *secondIconName; +@property (nonatomic, copy) NSString *thirdIconName; +@property (nonatomic, copy) NSString *fourthIconName; + +@property (nonatomic, strong) UIColor *firstColor; +@property (nonatomic, strong) UIColor *secondColor; +@property (nonatomic, strong) UIColor *thirdColor; +@property (nonatomic, strong) UIColor *fourthColor; + +// Color for background, when any state hasn't triggered yet +@property (nonatomic, strong) UIColor *defaultColor; + +// This is the general mode for all states +// If a specific mode for a state isn't defined, this mode will be taken in action +@property (nonatomic, assign) MCSwipeTableViewCellMode mode; + +// Individual mode for states +@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState1; +@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState2; +@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState3; +@property (nonatomic, assign) MCSwipeTableViewCellMode modeForState4; + +@property (nonatomic, assign) BOOL isDragging; +@property (nonatomic, assign) BOOL shouldDrag; +@property (nonatomic, assign) BOOL shouldAnimatesIcons; + +- (id)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString *)reuseIdentifier + firstStateIconName:(NSString *)firstIconName + firstColor:(UIColor *)firstColor +secondStateIconName:(NSString *)secondIconName + secondColor:(UIColor *)secondColor + thirdIconName:(NSString *)thirdIconName + thirdColor:(UIColor *)thirdColor + fourthIconName:(NSString *)fourthIconName + fourthColor:(UIColor *)fourthColor; + +- (void)setFirstStateIconName:(NSString *)firstIconName + firstColor:(UIColor *)firstColor + secondStateIconName:(NSString *)secondIconName + secondColor:(UIColor *)secondColor + thirdIconName:(NSString *)thirdIconName + thirdColor:(UIColor *)thirdColor + fourthIconName:(NSString *)fourthIconName + fourthColor:(UIColor *)fourthColor; + +@end diff --git a/clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.m b/clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.m new file mode 100755 index 000000000..b56d7cd69 --- /dev/null +++ b/clients/ios/Other Sources/MCSwipeTableViewCell/MCSwipeTableViewCell.m @@ -0,0 +1,559 @@ +// +// MCSwipeTableViewCell.m +// MCSwipeTableViewCell +// +// Created by Ali Karagoz on 24/02/13. +// Copyright (c) 2013 Mad Castle. All rights reserved. +// + +#import "MCSwipeTableViewCell.h" + +static CGFloat const kMCStop1 = 0.15; // Percentage limit to trigger the first action +static CGFloat const kMCStop2 = 0.75; // Percentage limit to trigger the second action +static CGFloat const kMCBounceAmplitude = 20.0; // Maximum bounce amplitude when using the MCSwipeTableViewCellModeSwitch mode +static NSTimeInterval const kMCBounceDuration1 = 0.2; // Duration of the first part of the bounce animation +static NSTimeInterval const kMCBounceDuration2 = 0.1; // Duration of the second part of the bounce animation +static NSTimeInterval const kMCDurationLowLimit = 0.25; // Lowest duration when swipping the cell because we try to simulate velocity +static NSTimeInterval const kMCDurationHightLimit = 0.1; // Highest duration when swipping the cell because we try to simulate velocity + +@interface MCSwipeTableViewCell () + +@property (nonatomic, assign) MCSwipeTableViewCellDirection direction; +@property (nonatomic, assign) CGFloat currentPercentage; + +@property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer; +@property (nonatomic, strong) UIImageView *slidingImageView; +@property (nonatomic, strong) NSString *currentImageName; +@property (nonatomic, strong) UIView *colorIndicatorView; + +@end + +@implementation MCSwipeTableViewCell + +#pragma mark - Initialization + +- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + [self initializer]; + } + return self; +} +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + [self initializer]; + } + return self; +} +- (id)init { + self = [super init]; + if (self) { + [self initializer]; + } + return self; +} + +#pragma mark - Custom Initializer + +- (id)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString *)reuseIdentifier + firstStateIconName:(NSString *)firstIconName + firstColor:(UIColor *)firstColor +secondStateIconName:(NSString *)secondIconName + secondColor:(UIColor *)secondColor + thirdIconName:(NSString *)thirdIconName + thirdColor:(UIColor *)thirdColor + fourthIconName:(NSString *)fourthIconName + fourthColor:(UIColor *)fourthColor { + + self = [self initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + [self setFirstStateIconName:firstIconName + firstColor:firstColor + secondStateIconName:secondIconName + secondColor:secondColor + thirdIconName:thirdIconName + thirdColor:thirdColor + fourthIconName:fourthIconName + fourthColor:fourthColor]; + } + return self; +} + +- (void)initializer { + + _mode = MCSwipeTableViewCellModeNone; + + _colorIndicatorView = [[UIView alloc] initWithFrame:self.bounds]; + [_colorIndicatorView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth]; + [_colorIndicatorView setBackgroundColor:(self.defaultColor ? self.defaultColor : [UIColor clearColor])]; + [self insertSubview:_colorIndicatorView atIndex:0]; + + _slidingImageView = [[UIImageView alloc] init]; + [_slidingImageView setContentMode:UIViewContentModeCenter]; + [_colorIndicatorView addSubview:_slidingImageView]; + + _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestureRecognizer:)]; + [self addGestureRecognizer:_panGestureRecognizer]; + [_panGestureRecognizer setDelegate:self]; + + _isDragging = NO; + + // By default the cells are draggable + _shouldDrag = YES; + + // By default the icons are animating + _shouldAnimatesIcons = YES; + + // Set state modes + _modeForState1 = MCSwipeTableViewCellModeNone; + _modeForState2 = MCSwipeTableViewCellModeNone; + _modeForState3 = MCSwipeTableViewCellModeNone; + _modeForState4 = MCSwipeTableViewCellModeNone; +} + +#pragma mark - Setter + +- (void)setFirstStateIconName:(NSString *)firstIconName + firstColor:(UIColor *)firstColor + secondStateIconName:(NSString *)secondIconName + secondColor:(UIColor *)secondColor + thirdIconName:(NSString *)thirdIconName + thirdColor:(UIColor *)thirdColor + fourthIconName:(NSString *)fourthIconName + fourthColor:(UIColor *)fourthColor { + + [self setFirstIconName:firstIconName]; + [self setSecondIconName:secondIconName]; + [self setThirdIconName:thirdIconName]; + [self setFourthIconName:fourthIconName]; + + [self setFirstColor:firstColor]; + [self setSecondColor:secondColor]; + [self setThirdColor:thirdColor]; + [self setFourthColor:fourthColor]; +} + +#pragma mark - Prepare reuse +- (void)prepareForReuse { + [super prepareForReuse]; + + // Clearing before presenting back the cell to the user + [_colorIndicatorView setBackgroundColor:[UIColor clearColor]]; + + // clearing the dragging flag + _isDragging = NO; + + // Before reuse we need to reset it's state + _shouldDrag = YES; + _shouldAnimatesIcons = YES; + _mode = MCSwipeTableViewCellModeNone; + _modeForState1 = MCSwipeTableViewCellModeNone; + _modeForState2 = MCSwipeTableViewCellModeNone; + _modeForState3 = MCSwipeTableViewCellModeNone; + _modeForState4 = MCSwipeTableViewCellModeNone; +} + +#pragma mark - Handle Gestures + +- (void)handlePanGestureRecognizer:(UIPanGestureRecognizer *)gesture { + + // The user do not want you to be dragged! + if (!_shouldDrag) return; + + UIGestureRecognizerState state = [gesture state]; + CGPoint translation = [gesture translationInView:self]; + CGPoint velocity = [gesture velocityInView:self]; + CGFloat percentage = [self percentageWithOffset:CGRectGetMinX(self.contentView.frame) relativeToWidth:CGRectGetWidth(self.bounds)]; + NSTimeInterval animationDuration = [self animationDurationWithVelocity:velocity]; + _direction = [self directionWithPercentage:percentage]; + + if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged) { + _isDragging = YES; + + CGPoint center = {self.contentView.center.x + translation.x, self.contentView.center.y}; + NSLog(@"Center: %@", NSStringFromCGPoint(center)); + [self.contentView setCenter:center]; + [self animateWithOffset:CGRectGetMinX(self.contentView.frame)]; + [gesture setTranslation:CGPointZero inView:self]; + + // Notifying the delegate that we are dragging with an offset percentage + if ([_delegate respondsToSelector:@selector(swipeTableViewCell:didSwipWithPercentage:)]) { + [_delegate swipeTableViewCell:self didSwipWithPercentage:percentage]; + } + } + + else if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled) { + _isDragging = NO; + + _currentImageName = [self imageNameWithPercentage:percentage]; + _currentPercentage = percentage; + + // Current state + MCSwipeTableViewCellState cellState = [self stateWithPercentage:percentage]; + + // Current mode + MCSwipeTableViewCellMode cellMode; + + if (cellState == MCSwipeTableViewCellState1 && self.modeForState1 != MCSwipeTableViewCellModeNone) { + cellMode = self.modeForState1; + } else if (cellState == MCSwipeTableViewCellState2 && self.modeForState2 != MCSwipeTableViewCellModeNone) { + cellMode = self.modeForState2; + } else if (cellState == MCSwipeTableViewCellState3 && self.modeForState3 != MCSwipeTableViewCellModeNone) { + cellMode = self.modeForState3; + } else if (cellState == MCSwipeTableViewCellState4 && self.modeForState4 != MCSwipeTableViewCellModeNone) { + cellMode = self.modeForState4; + } else { + cellMode = self.mode; + } + + if (cellMode == MCSwipeTableViewCellModeExit && _direction != MCSwipeTableViewCellDirectionCenter && [self validateState:cellState]) + [self moveWithDuration:animationDuration andDirection:_direction]; + else + [self bounceToOrigin]; + } +} + +#pragma mark - UIGestureRecognizerDelegate +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + if ([gestureRecognizer class] == [UIPanGestureRecognizer class]) { + + UIPanGestureRecognizer *g = (UIPanGestureRecognizer *)gestureRecognizer; + CGPoint point = [g velocityInView:self]; + + if (fabsf(point.x) > fabsf(point.y) ) { + + // We notify the delegate that we just started dragging + if ([_delegate respondsToSelector:@selector(swipeTableViewCellDidStartSwiping:)]) { + [_delegate swipeTableViewCellDidStartSwiping:self]; + } + + return YES; + } + } + return NO; +} + +#pragma mark - Utils +- (CGFloat)offsetWithPercentage:(CGFloat)percentage relativeToWidth:(CGFloat)width { + CGFloat offset = percentage * width; + + if (offset < -width) offset = -width; + else if (offset > width) offset = width; + + return offset; +} + +- (CGFloat)percentageWithOffset:(CGFloat)offset relativeToWidth:(CGFloat)width { + CGFloat percentage = offset / width; + + if (percentage < -1.0) percentage = -1.0; + else if (percentage > 1.0) percentage = 1.0; + + return percentage; +} + +- (NSTimeInterval)animationDurationWithVelocity:(CGPoint)velocity { + CGFloat width = CGRectGetWidth(self.bounds); + NSTimeInterval animationDurationDiff = kMCDurationHightLimit - kMCDurationLowLimit; + CGFloat horizontalVelocity = velocity.x; + + if (horizontalVelocity < -width) horizontalVelocity = -width; + else if (horizontalVelocity > width) horizontalVelocity = width; + + return (kMCDurationHightLimit + kMCDurationLowLimit) - fabs(((horizontalVelocity / width) * animationDurationDiff)); +} + +- (MCSwipeTableViewCellDirection)directionWithPercentage:(CGFloat)percentage { + if (percentage < 0) + return MCSwipeTableViewCellDirectionLeft; + else if (percentage > 0) + return MCSwipeTableViewCellDirectionRight; + else + return MCSwipeTableViewCellDirectionCenter; +} + +- (NSString *)imageNameWithPercentage:(CGFloat)percentage { + NSString *imageName; + + // Image + if (percentage >= 0 && percentage < kMCStop2) + imageName = _firstIconName; + else if (percentage >= kMCStop2) + imageName = _secondIconName; + else if (percentage < 0 && percentage > -kMCStop2) + imageName = _thirdIconName; + else if (percentage <= -kMCStop2) + imageName = _fourthIconName; + + return imageName; +} +- (CGFloat)imageAlphaWithPercentage:(CGFloat)percentage { + CGFloat alpha; + + if (percentage >= 0 && percentage < kMCStop1) + alpha = percentage / kMCStop1; + else if (percentage < 0 && percentage > -kMCStop1) + alpha = fabsf(percentage / kMCStop1); + else alpha = 1.0; + + return alpha; +} + +- (UIColor *)colorWithPercentage:(CGFloat)percentage { + UIColor *color; + + // Background Color + if (percentage >= kMCStop1 && percentage < kMCStop2) + color = _firstColor; + else if (percentage >= kMCStop2) + color = _secondColor; + else if (percentage < -kMCStop1 && percentage > -kMCStop2) + color = _thirdColor; + else if (percentage <= -kMCStop2) + color = _fourthColor; + else + color = self.defaultColor ? self.defaultColor : [UIColor clearColor]; + + return color; +} + +- (MCSwipeTableViewCellState)stateWithPercentage:(CGFloat)percentage { + MCSwipeTableViewCellState state; + + state = MCSwipeTableViewCellStateNone; + + if (percentage >= kMCStop1 && [self validateState:MCSwipeTableViewCellState1]) + state = MCSwipeTableViewCellState1; + + if (percentage >= kMCStop2 && [self validateState:MCSwipeTableViewCellState2]) + state = MCSwipeTableViewCellState2; + + if (percentage <= -kMCStop1 && [self validateState:MCSwipeTableViewCellState3]) + state = MCSwipeTableViewCellState3; + + if (percentage <= -kMCStop2 && [self validateState:MCSwipeTableViewCellState4]) + state = MCSwipeTableViewCellState4; + + return state; +} + +- (BOOL)validateState:(MCSwipeTableViewCellState)state { + BOOL isValid = YES; + + switch (state) { + case MCSwipeTableViewCellStateNone: { + isValid = NO; + } + break; + + case MCSwipeTableViewCellState1: { + if (!_firstColor && !_firstIconName) + isValid = NO; + } + break; + + case MCSwipeTableViewCellState2: { + if (!_secondColor && !_secondIconName) + isValid = NO; + } + break; + + case MCSwipeTableViewCellState3: { + if (!_thirdColor && !_thirdIconName) + isValid = NO; + } + break; + + case MCSwipeTableViewCellState4: { + if (!_fourthColor && !_fourthIconName) + isValid = NO; + } + break; + + default: + break; + } + + return isValid; +} + +#pragma mark - Movement + +- (void)animateWithOffset:(CGFloat)offset { + CGFloat percentage = [self percentageWithOffset:offset relativeToWidth:CGRectGetWidth(self.bounds)]; + + // Image Name + NSString *imageName = [self imageNameWithPercentage:percentage]; + + // Image Position + if (imageName != nil) { + [_slidingImageView setImage:[UIImage imageNamed:imageName]]; + [_slidingImageView setAlpha:[self imageAlphaWithPercentage:percentage]]; + [self slideImageWithPercentage:percentage imageName:imageName isDragging:self.shouldAnimatesIcons]; + } + + // Color + UIColor *color = [self colorWithPercentage:percentage]; + if (color != nil) { + [_colorIndicatorView setBackgroundColor:color]; + } +} + +- (void)slideImageWithPercentage:(CGFloat)percentage imageName:(NSString *)imageName isDragging:(BOOL)isDragging { + UIImage *slidingImage = [UIImage imageNamed:imageName]; + CGSize slidingImageSize = slidingImage.size; + CGRect slidingImageRect; + + CGPoint position = CGPointZero; + + position.y = CGRectGetHeight(self.bounds) / 2.0; + + if (isDragging) { + if (percentage >= 0 && percentage < kMCStop1) { + position.x = [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)]; + } + + else if (percentage >= kMCStop1) { + position.x = [self offsetWithPercentage:percentage - (kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)]; + } + else if (percentage < 0 && percentage >= -kMCStop1) { + position.x = CGRectGetWidth(self.bounds) - [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)]; + } + + else if (percentage < -kMCStop1) { + position.x = CGRectGetWidth(self.bounds) + [self offsetWithPercentage:percentage + (kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)]; + } + } + else { + if (_direction == MCSwipeTableViewCellDirectionRight) { + position.x = [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)]; + } + else if (_direction == MCSwipeTableViewCellDirectionLeft) { + position.x = CGRectGetWidth(self.bounds) - [self offsetWithPercentage:(kMCStop1 / 2) relativeToWidth:CGRectGetWidth(self.bounds)]; + } + else { + return; + } + } + + + slidingImageRect = CGRectMake(position.x - slidingImageSize.width / 2.0, + position.y - slidingImageSize.height / 2.0, + slidingImageSize.width, + slidingImageSize.height); + + slidingImageRect = CGRectIntegral(slidingImageRect); + [_slidingImageView setFrame:slidingImageRect]; +} + +- (void)moveWithDuration:(NSTimeInterval)duration andDirection:(MCSwipeTableViewCellDirection)direction { + CGFloat origin; + + if (direction == MCSwipeTableViewCellDirectionLeft) + origin = -CGRectGetWidth(self.bounds); + else + origin = CGRectGetWidth(self.bounds); + + CGFloat percentage = [self percentageWithOffset:origin relativeToWidth:CGRectGetWidth(self.bounds)]; + CGRect rect = self.contentView.frame; + rect.origin.x = origin; + + // Color + UIColor *color = [self colorWithPercentage:_currentPercentage]; + if (color != nil) { + [_colorIndicatorView setBackgroundColor:color]; + } + + // Image + if (_currentImageName != nil) { + [_slidingImageView setImage:[UIImage imageNamed:_currentImageName]]; + } + + [UIView animateWithDuration:duration + delay:0.0 + options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction) + animations:^{ + [self.contentView setFrame:rect]; + [_slidingImageView setAlpha:0]; + [self slideImageWithPercentage:percentage imageName:_currentImageName isDragging:self.shouldAnimatesIcons]; + } + completion:^(BOOL finished) { + [self notifyDelegate]; + }]; +} + +- (void)bounceToOrigin { + CGFloat bounceDistance = kMCBounceAmplitude * _currentPercentage; + + [UIView animateWithDuration:kMCBounceDuration1 + delay:0 + options:(UIViewAnimationOptionCurveEaseOut) + animations:^{ + CGRect frame = self.contentView.frame; + frame.origin.x = -bounceDistance; + [self.contentView setFrame:frame]; + [_slidingImageView setAlpha:0.0]; + [self slideImageWithPercentage:0 imageName:_currentImageName isDragging:NO]; + + // Setting back the color to the default + _colorIndicatorView.backgroundColor = self.defaultColor; + } + completion:^(BOOL finished1) { + + [UIView animateWithDuration:kMCBounceDuration2 + delay:0 + options:UIViewAnimationOptionCurveEaseIn + animations:^{ + CGRect frame = self.contentView.frame; + frame.origin.x = 0; + [self.contentView setFrame:frame]; + + // Clearing the indicator view + _colorIndicatorView.backgroundColor = [UIColor clearColor]; + } + completion:^(BOOL finished2) { + [self notifyDelegate]; + }]; + }]; +} + +#pragma mark - Delegate Notification + +- (void)notifyDelegate { + MCSwipeTableViewCellState state = [self stateWithPercentage:_currentPercentage]; + + MCSwipeTableViewCellMode mode = self.mode; + + if (mode == MCSwipeTableViewCellModeNone) { + switch (state) { + case MCSwipeTableViewCellState1: { + mode = self.modeForState1; + } break; + + case MCSwipeTableViewCellState2: { + mode = self.modeForState2; + } break; + + case MCSwipeTableViewCellState3: { + mode = self.modeForState3; + } break; + + case MCSwipeTableViewCellState4: { + mode = self.modeForState4; + } break; + + default: + break; + } + } + + if (state != MCSwipeTableViewCellStateNone) { + if ([_delegate respondsToSelector:@selector(swipeTableViewCell:didEndSwipingSwipingWithState:mode:)]) { + [_delegate swipeTableViewCell:self didEndSwipingSwipingWithState:state mode:mode]; + } + } +} + +@end \ No newline at end of file