diff --git a/AsyncDisplayKit/ASCollectionNode.h b/AsyncDisplayKit/ASCollectionNode.h index 488f1ba73d..dad0bd76c6 100644 --- a/AsyncDisplayKit/ASCollectionNode.h +++ b/AsyncDisplayKit/ASCollectionNode.h @@ -74,6 +74,12 @@ NS_ASSUME_NONNULL_BEGIN */ @property (weak, nonatomic) id dataSource; +/* + * A Boolean value that determines whether the collection node will be flipped. + * If the value of this property is YES, the first cell node will be at the bottom of the collection node (as opposed to the top by default). This is useful for chat/messaging apps. The default value is NO. + */ +@property (nonatomic, assign) BOOL inverted; + /** * A Boolean value that indicates whether users can select items in the collection node. * If the value of this property is YES (the default), users can select items. If you want more fine-grained control over the selection of items, you must provide a delegate object and implement the appropriate methods of the UICollectionNodeDelegate protocol. diff --git a/AsyncDisplayKit/ASCollectionNode.mm b/AsyncDisplayKit/ASCollectionNode.mm index 708307c755..07e9010a9d 100644 --- a/AsyncDisplayKit/ASCollectionNode.mm +++ b/AsyncDisplayKit/ASCollectionNode.mm @@ -31,6 +31,7 @@ @property (nonatomic, assign) ASLayoutRangeMode rangeMode; @property (nonatomic, assign) BOOL allowsSelection; // default is YES @property (nonatomic, assign) BOOL allowsMultipleSelection; // default is NO +@property (nonatomic, assign) BOOL inverted; //default is NO @end @implementation _ASCollectionPendingState @@ -42,6 +43,7 @@ _rangeMode = ASLayoutRangeModeCount; _allowsSelection = YES; _allowsMultipleSelection = NO; + _inverted = NO; } return self; } @@ -148,6 +150,7 @@ self.pendingState = nil; view.asyncDelegate = pendingState.delegate; view.asyncDataSource = pendingState.dataSource; + view.inverted = pendingState.inverted; view.allowsSelection = pendingState.allowsSelection; view.allowsMultipleSelection = pendingState.allowsMultipleSelection; @@ -217,6 +220,26 @@ return _pendingState; } +- (void)setInverted:(BOOL)inverted +{ + self.transform = inverted ? CATransform3DMakeScale(1, -1, 1) : CATransform3DIdentity; + if ([self pendingState]) { + _pendingState.inverted = inverted; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist"); + self.view.inverted = inverted; + } +} + +- (BOOL)inverted +{ + if ([self pendingState]) { + return _pendingState.inverted; + } else { + return self.view.inverted; + } +} + - (void)setDelegate:(id )delegate { if ([self pendingState]) { diff --git a/AsyncDisplayKit/ASCollectionView.h b/AsyncDisplayKit/ASCollectionView.h index 3e200bf60e..802a6b24b6 100644 --- a/AsyncDisplayKit/ASCollectionView.h +++ b/AsyncDisplayKit/ASCollectionView.h @@ -106,6 +106,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, readonly) ASScrollDirection scrollableDirections; +/* + * A Boolean value that determines whether the nodes that the data source renders will be flipped. + */ +@property (nonatomic, assign) BOOL inverted; + /** * Forces the .contentInset to be UIEdgeInsetsZero. * diff --git a/AsyncDisplayKit/ASCollectionView.mm b/AsyncDisplayKit/ASCollectionView.mm index 463052478d..73be431bbd 100644 --- a/AsyncDisplayKit/ASCollectionView.mm +++ b/AsyncDisplayKit/ASCollectionView.mm @@ -1408,6 +1408,9 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier"; if (node.interactionDelegate == nil) { node.interactionDelegate = strongSelf; } + if (_inverted) { + node.transform = CATransform3DMakeScale(1, -1, 1) ; + } return node; }; return block; diff --git a/AsyncDisplayKit/ASTableNode.h b/AsyncDisplayKit/ASTableNode.h index 72817e04b7..4222f1afa2 100644 --- a/AsyncDisplayKit/ASTableNode.h +++ b/AsyncDisplayKit/ASTableNode.h @@ -35,6 +35,11 @@ NS_ASSUME_NONNULL_BEGIN @property (weak, nonatomic) id delegate; @property (weak, nonatomic) id dataSource; +/* + * A Boolean value that determines whether the table will be flipped. + * If the value of this property is YES, the first cell node will be at the bottom of the table (as opposed to the top by default). This is useful for chat/messaging apps. The default value is NO. + */ +@property (nonatomic, assign) BOOL inverted; /* * A Boolean value that determines whether users can select a row. * If the value of this property is YES (the default), users can select rows. If you set it to NO, they cannot select rows. Setting this property affects cell selection only when the table view is not in editing mode. If you want to restrict selection of cells in editing mode, use `allowsSelectionDuringEditing`. diff --git a/AsyncDisplayKit/ASTableNode.mm b/AsyncDisplayKit/ASTableNode.mm index 1101847bf5..d80d996983 100644 --- a/AsyncDisplayKit/ASTableNode.mm +++ b/AsyncDisplayKit/ASTableNode.mm @@ -30,6 +30,7 @@ @property (nonatomic, assign) BOOL allowsSelectionDuringEditing; @property (nonatomic, assign) BOOL allowsMultipleSelection; @property (nonatomic, assign) BOOL allowsMultipleSelectionDuringEditing; +@property (nonatomic, assign) BOOL inverted; @end @implementation _ASTablePendingState @@ -42,6 +43,7 @@ _allowsSelectionDuringEditing = NO; _allowsMultipleSelection = NO; _allowsMultipleSelectionDuringEditing = NO; + _inverted = NO; } return self; } @@ -116,6 +118,7 @@ self.pendingState = nil; view.asyncDelegate = pendingState.delegate; view.asyncDataSource = pendingState.dataSource; + view.inverted = pendingState.inverted; view.allowsSelection = pendingState.allowsSelection; view.allowsSelectionDuringEditing = pendingState.allowsSelectionDuringEditing; view.allowsMultipleSelection = pendingState.allowsMultipleSelection; @@ -186,6 +189,26 @@ return _pendingState; } +- (void)setInverted:(BOOL)inverted +{ + self.transform = inverted ? CATransform3DMakeScale(1, -1, 1) : CATransform3DIdentity; + if ([self pendingState]) { + _pendingState.inverted = inverted; + } else { + ASDisplayNodeAssert([self isNodeLoaded], @"ASTableNode should be loaded if pendingState doesn't exist"); + self.view.inverted = inverted; + } +} + +- (BOOL)inverted +{ + if ([self pendingState]) { + return _pendingState.inverted; + } else { + return self.view.inverted; + } +} + - (void)setDelegate:(id )delegate { if ([self pendingState]) { diff --git a/AsyncDisplayKit/ASTableView.h b/AsyncDisplayKit/ASTableView.h index b932edc873..e3ceeaaaec 100644 --- a/AsyncDisplayKit/ASTableView.h +++ b/AsyncDisplayKit/ASTableView.h @@ -59,6 +59,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign) CGFloat leadingScreensForBatching; +/* + * A Boolean value that determines whether the nodes that the data source renders will be flipped. + */ +@property (nonatomic, assign) BOOL inverted; + @end @interface ASTableView (Deprecated) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index ba6614ed66..ca2b4a0659 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -1551,6 +1551,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; if (node.interactionDelegate == nil) { node.interactionDelegate = strongSelf; } + if (_inverted) { + node.transform = CATransform3DMakeScale(1, -1, 1) ; + } return node; }; return block; diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index a93ce23e54..df12fcfe1d 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -912,7 +912,6 @@ NSString * const ASCollectionInvalidUpdateException = @"ASCollectionInvalidUpdat context = completedNodesSection[row]; } } - return context.node; } diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index 024b49feff..b2ca9b6e1b 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -218,10 +218,10 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { ASDisplayNo _bridge_prologue_read; // Frame is only defined when transform is identity. -#if DEBUG - // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of. - ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode frame] - self.transform must be identity in order to use the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"); -#endif +//#if DEBUG +// // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of. +// ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode frame] - self.transform must be identity in order to use the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"); +//#endif CGPoint position = self.position; CGRect bounds = self.bounds; @@ -277,10 +277,10 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { ASDisplayNo // We do have to set frame directly, and we're on main thread with a loaded node. // Just set the frame on the view. // NOTE: Frame is only defined when transform is identity because we explicitly diverge from CALayer behavior and define frame without transform. -#if DEBUG - // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of. - ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"); -#endif +//#if DEBUG +// // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of. +// ASDisplayNodeAssert(CATransform3DIsIdentity(self.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"); +//#endif _view.frame = rect; } else { // We do have to set frame directly, but either the node isn't loaded or we're on a non-main thread. diff --git a/AsyncDisplayKit/Private/_ASPendingState.mm b/AsyncDisplayKit/Private/_ASPendingState.mm index c01470e258..04547da5ca 100644 --- a/AsyncDisplayKit/Private/_ASPendingState.mm +++ b/AsyncDisplayKit/Private/_ASPendingState.mm @@ -947,10 +947,10 @@ static BOOL defaultAllowsEdgeAntialiasing = NO; if (flags.setFrame && specialPropertiesHandling) { // Frame is only defined when transform is identity because we explicitly diverge from CALayer behavior and define frame without transform -#if DEBUG - // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of. - ASDisplayNodeAssert(CATransform3DIsIdentity(layer.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"); -#endif +//#if DEBUG +// // Checking if the transform is identity is expensive, so disable when unnecessary. We have assertions on in Release, so DEBUG is the only way I know of. +// ASDisplayNodeAssert(CATransform3DIsIdentity(layer.transform), @"-[ASDisplayNode setFrame:] - self.transform must be identity in order to set the frame property. (From Apple's UIView documentation: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.)"); +//#endif view.frame = frame; } else { ASPendingStateApplyMetricsToLayer(self, layer); diff --git a/examples/SocialAppLayout-Inverted/Podfile b/examples/SocialAppLayout-Inverted/Podfile new file mode 100644 index 0000000000..919de4b311 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Podfile @@ -0,0 +1,5 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '7.0' +target 'Sample' do + pod 'AsyncDisplayKit', :path => '../..' +end diff --git a/examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.pbxproj b/examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..3ef0e517e9 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.pbxproj @@ -0,0 +1,484 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 3EEA4EE91BECC4A1008A7F35 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4EE81BECC4A1008A7F35 /* main.m */; }; + 3EEA4EEC1BECC4A1008A7F35 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4EEB1BECC4A1008A7F35 /* AppDelegate.m */; }; + 3EEA4EEF1BECC4A1008A7F35 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4EEE1BECC4A1008A7F35 /* ViewController.m */; }; + 3EEA4EF41BECC4A1008A7F35 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4EF31BECC4A1008A7F35 /* Assets.xcassets */; }; + 3EEA4F011BECC4E8008A7F35 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4EFE1BECC4E8008A7F35 /* Default-568h@2x.png */; }; + 3EEA4F021BECC4E8008A7F35 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4EFF1BECC4E8008A7F35 /* Default-667h@2x.png */; }; + 3EEA4F031BECC4E8008A7F35 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F001BECC4E8008A7F35 /* Default-736h@3x.png */; }; + 3EEA4F061BECC6C9008A7F35 /* Post.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4F051BECC6C9008A7F35 /* Post.m */; }; + 3EEA4F091BECC855008A7F35 /* PostNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4F081BECC855008A7F35 /* PostNode.m */; }; + 3EEA4F0C1BECCA0A008A7F35 /* TextStyles.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4F0B1BECCA0A008A7F35 /* TextStyles.m */; }; + 3EEA4F141BECDCD6008A7F35 /* icon_android.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F0E1BECDCD6008A7F35 /* icon_android.png */; }; + 3EEA4F151BECDCD6008A7F35 /* icon_android@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F0F1BECDCD6008A7F35 /* icon_android@2x.png */; }; + 3EEA4F161BECDCD6008A7F35 /* icon_android@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F101BECDCD6008A7F35 /* icon_android@3x.png */; }; + 3EEA4F171BECDCD6008A7F35 /* icon_ios.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F111BECDCD6008A7F35 /* icon_ios.png */; }; + 3EEA4F181BECDCD6008A7F35 /* icon_ios@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F121BECDCD6008A7F35 /* icon_ios@2x.png */; }; + 3EEA4F191BECDCD6008A7F35 /* icon_ios@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F131BECDCD6008A7F35 /* icon_ios@3x.png */; }; + 3EEA4F1D1BECE358008A7F35 /* LikesNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4F1C1BECE358008A7F35 /* LikesNode.m */; }; + 3EEA4F2A1BECE440008A7F35 /* icon_liked.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F1E1BECE440008A7F35 /* icon_liked.png */; }; + 3EEA4F2B1BECE440008A7F35 /* icon_liked@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F1F1BECE440008A7F35 /* icon_liked@2x.png */; }; + 3EEA4F2C1BECE440008A7F35 /* icon_liked@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F201BECE440008A7F35 /* icon_liked@3x.png */; }; + 3EEA4F301BECE440008A7F35 /* icon_like@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F241BECE440008A7F35 /* icon_like@3x.png */; }; + 3EEA4F311BECE440008A7F35 /* icon_like@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F251BECE440008A7F35 /* icon_like@2x.png */; }; + 3EEA4F321BECE440008A7F35 /* icon_like.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F261BECE440008A7F35 /* icon_like.png */; }; + 3EEA4F331BECE440008A7F35 /* icon_comment@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F271BECE440008A7F35 /* icon_comment@3x.png */; }; + 3EEA4F341BECE440008A7F35 /* icon_comment@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F281BECE440008A7F35 /* icon_comment@2x.png */; }; + 3EEA4F351BECE440008A7F35 /* icon_comment.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F291BECE440008A7F35 /* icon_comment.png */; }; + 3EEA4F381BECE775008A7F35 /* CommentsNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EEA4F371BECE775008A7F35 /* CommentsNode.m */; }; + 3EEA4F3C1BECE99F008A7F35 /* icon_more.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F391BECE99F008A7F35 /* icon_more.png */; }; + 3EEA4F3D1BECE99F008A7F35 /* icon_more@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F3A1BECE99F008A7F35 /* icon_more@2x.png */; }; + 3EEA4F3E1BECE99F008A7F35 /* icon_more@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3EEA4F3B1BECE99F008A7F35 /* icon_more@3x.png */; }; + 93964C9FCC28D92625106430 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 193CE60FE6429EFEBF6EA52B /* libPods-Sample.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 193CE60FE6429EFEBF6EA52B /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3EEA4EE41BECC4A1008A7F35 /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3EEA4EE81BECC4A1008A7F35 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 3EEA4EEA1BECC4A1008A7F35 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 3EEA4EEB1BECC4A1008A7F35 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 3EEA4EED1BECC4A1008A7F35 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 3EEA4EEE1BECC4A1008A7F35 /* ViewController.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; tabWidth = 2; }; + 3EEA4EF31BECC4A1008A7F35 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 3EEA4EF81BECC4A1008A7F35 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3EEA4EFE1BECC4E8008A7F35 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 3EEA4EFF1BECC4E8008A7F35 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = ""; }; + 3EEA4F001BECC4E8008A7F35 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = ""; }; + 3EEA4F041BECC6C9008A7F35 /* Post.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Post.h; sourceTree = ""; }; + 3EEA4F051BECC6C9008A7F35 /* Post.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Post.m; sourceTree = ""; }; + 3EEA4F071BECC855008A7F35 /* PostNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PostNode.h; sourceTree = ""; }; + 3EEA4F081BECC855008A7F35 /* PostNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PostNode.m; sourceTree = ""; }; + 3EEA4F0A1BECCA0A008A7F35 /* TextStyles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextStyles.h; sourceTree = ""; }; + 3EEA4F0B1BECCA0A008A7F35 /* TextStyles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextStyles.m; sourceTree = ""; }; + 3EEA4F0E1BECDCD6008A7F35 /* icon_android.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_android.png; sourceTree = ""; }; + 3EEA4F0F1BECDCD6008A7F35 /* icon_android@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_android@2x.png"; sourceTree = ""; }; + 3EEA4F101BECDCD6008A7F35 /* icon_android@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_android@3x.png"; sourceTree = ""; }; + 3EEA4F111BECDCD6008A7F35 /* icon_ios.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_ios.png; sourceTree = ""; }; + 3EEA4F121BECDCD6008A7F35 /* icon_ios@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_ios@2x.png"; sourceTree = ""; }; + 3EEA4F131BECDCD6008A7F35 /* icon_ios@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_ios@3x.png"; sourceTree = ""; }; + 3EEA4F1B1BECE358008A7F35 /* LikesNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LikesNode.h; sourceTree = ""; }; + 3EEA4F1C1BECE358008A7F35 /* LikesNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LikesNode.m; sourceTree = ""; }; + 3EEA4F1E1BECE440008A7F35 /* icon_liked.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_liked.png; sourceTree = ""; }; + 3EEA4F1F1BECE440008A7F35 /* icon_liked@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_liked@2x.png"; sourceTree = ""; }; + 3EEA4F201BECE440008A7F35 /* icon_liked@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_liked@3x.png"; sourceTree = ""; }; + 3EEA4F241BECE440008A7F35 /* icon_like@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_like@3x.png"; sourceTree = ""; }; + 3EEA4F251BECE440008A7F35 /* icon_like@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_like@2x.png"; sourceTree = ""; }; + 3EEA4F261BECE440008A7F35 /* icon_like.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_like.png; sourceTree = ""; }; + 3EEA4F271BECE440008A7F35 /* icon_comment@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_comment@3x.png"; sourceTree = ""; }; + 3EEA4F281BECE440008A7F35 /* icon_comment@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_comment@2x.png"; sourceTree = ""; }; + 3EEA4F291BECE440008A7F35 /* icon_comment.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_comment.png; sourceTree = ""; }; + 3EEA4F361BECE775008A7F35 /* CommentsNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommentsNode.h; sourceTree = ""; }; + 3EEA4F371BECE775008A7F35 /* CommentsNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommentsNode.m; sourceTree = ""; }; + 3EEA4F391BECE99F008A7F35 /* icon_more.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_more.png; sourceTree = ""; }; + 3EEA4F3A1BECE99F008A7F35 /* icon_more@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_more@2x.png"; sourceTree = ""; }; + 3EEA4F3B1BECE99F008A7F35 /* icon_more@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_more@3x.png"; sourceTree = ""; }; + CC6F2ABE8383FAB21802C734 /* Pods-Sample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.debug.xcconfig"; sourceTree = ""; }; + FCCC1AD413FCA8603156ED15 /* Pods-Sample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sample.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sample/Pods-Sample.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3EEA4EE11BECC4A1008A7F35 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 93964C9FCC28D92625106430 /* libPods-Sample.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3EEA4EDB1BECC4A1008A7F35 = { + isa = PBXGroup; + children = ( + 3EEA4EE61BECC4A1008A7F35 /* Sample */, + 3EEA4EE51BECC4A1008A7F35 /* Products */, + 842ADAFE88475D19B24183AC /* Pods */, + EED34FA6D8171DF44757C852 /* Frameworks */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + }; + 3EEA4EE51BECC4A1008A7F35 /* Products */ = { + isa = PBXGroup; + children = ( + 3EEA4EE41BECC4A1008A7F35 /* Sample.app */, + ); + name = Products; + sourceTree = ""; + }; + 3EEA4EE61BECC4A1008A7F35 /* Sample */ = { + isa = PBXGroup; + children = ( + 3EEA4F0D1BECDCA6008A7F35 /* Images */, + 3EEA4EEA1BECC4A1008A7F35 /* AppDelegate.h */, + 3EEA4EEB1BECC4A1008A7F35 /* AppDelegate.m */, + 3EEA4EED1BECC4A1008A7F35 /* ViewController.h */, + 3EEA4EEE1BECC4A1008A7F35 /* ViewController.m */, + 3EEA4EF31BECC4A1008A7F35 /* Assets.xcassets */, + 3EEA4EF81BECC4A1008A7F35 /* Info.plist */, + 3EEA4EE71BECC4A1008A7F35 /* Supporting Files */, + 3EEA4F041BECC6C9008A7F35 /* Post.h */, + 3EEA4F051BECC6C9008A7F35 /* Post.m */, + 3EEA4F071BECC855008A7F35 /* PostNode.h */, + 3EEA4F081BECC855008A7F35 /* PostNode.m */, + 3EEA4F0A1BECCA0A008A7F35 /* TextStyles.h */, + 3EEA4F0B1BECCA0A008A7F35 /* TextStyles.m */, + 3EEA4F1B1BECE358008A7F35 /* LikesNode.h */, + 3EEA4F1C1BECE358008A7F35 /* LikesNode.m */, + 3EEA4F361BECE775008A7F35 /* CommentsNode.h */, + 3EEA4F371BECE775008A7F35 /* CommentsNode.m */, + ); + path = Sample; + sourceTree = ""; + }; + 3EEA4EE71BECC4A1008A7F35 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 3EEA4EFE1BECC4E8008A7F35 /* Default-568h@2x.png */, + 3EEA4EFF1BECC4E8008A7F35 /* Default-667h@2x.png */, + 3EEA4F001BECC4E8008A7F35 /* Default-736h@3x.png */, + 3EEA4EE81BECC4A1008A7F35 /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 3EEA4F0D1BECDCA6008A7F35 /* Images */ = { + isa = PBXGroup; + children = ( + 3EEA4F391BECE99F008A7F35 /* icon_more.png */, + 3EEA4F3A1BECE99F008A7F35 /* icon_more@2x.png */, + 3EEA4F3B1BECE99F008A7F35 /* icon_more@3x.png */, + 3EEA4F1E1BECE440008A7F35 /* icon_liked.png */, + 3EEA4F1F1BECE440008A7F35 /* icon_liked@2x.png */, + 3EEA4F201BECE440008A7F35 /* icon_liked@3x.png */, + 3EEA4F241BECE440008A7F35 /* icon_like@3x.png */, + 3EEA4F251BECE440008A7F35 /* icon_like@2x.png */, + 3EEA4F261BECE440008A7F35 /* icon_like.png */, + 3EEA4F271BECE440008A7F35 /* icon_comment@3x.png */, + 3EEA4F281BECE440008A7F35 /* icon_comment@2x.png */, + 3EEA4F291BECE440008A7F35 /* icon_comment.png */, + 3EEA4F0E1BECDCD6008A7F35 /* icon_android.png */, + 3EEA4F0F1BECDCD6008A7F35 /* icon_android@2x.png */, + 3EEA4F101BECDCD6008A7F35 /* icon_android@3x.png */, + 3EEA4F111BECDCD6008A7F35 /* icon_ios.png */, + 3EEA4F121BECDCD6008A7F35 /* icon_ios@2x.png */, + 3EEA4F131BECDCD6008A7F35 /* icon_ios@3x.png */, + ); + name = Images; + sourceTree = ""; + }; + 842ADAFE88475D19B24183AC /* Pods */ = { + isa = PBXGroup; + children = ( + CC6F2ABE8383FAB21802C734 /* Pods-Sample.debug.xcconfig */, + FCCC1AD413FCA8603156ED15 /* Pods-Sample.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + EED34FA6D8171DF44757C852 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 193CE60FE6429EFEBF6EA52B /* libPods-Sample.a */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3EEA4EE31BECC4A1008A7F35 /* Sample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3EEA4EFB1BECC4A1008A7F35 /* Build configuration list for PBXNativeTarget "Sample" */; + buildPhases = ( + B5BD9E5609B2CB179EEE0CF4 /* [CP] Check Pods Manifest.lock */, + 3EEA4EE01BECC4A1008A7F35 /* Sources */, + 3EEA4EE11BECC4A1008A7F35 /* Frameworks */, + 3EEA4EE21BECC4A1008A7F35 /* Resources */, + 21F2C1D9B53F9468EAF1653F /* [CP] Copy Pods Resources */, + 852437589F1D53B9483A75DF /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Sample; + productName = Sample; + productReference = 3EEA4EE41BECC4A1008A7F35 /* Sample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3EEA4EDC1BECC4A1008A7F35 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 3EEA4EE31BECC4A1008A7F35 = { + CreatedOnToolsVersion = 7.1; + }; + }; + }; + buildConfigurationList = 3EEA4EDF1BECC4A1008A7F35 /* Build configuration list for PBXProject "Sample" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3EEA4EDB1BECC4A1008A7F35; + productRefGroup = 3EEA4EE51BECC4A1008A7F35 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3EEA4EE31BECC4A1008A7F35 /* Sample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3EEA4EE21BECC4A1008A7F35 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EEA4F2A1BECE440008A7F35 /* icon_liked.png in Resources */, + 3EEA4F181BECDCD6008A7F35 /* icon_ios@2x.png in Resources */, + 3EEA4F311BECE440008A7F35 /* icon_like@2x.png in Resources */, + 3EEA4F3D1BECE99F008A7F35 /* icon_more@2x.png in Resources */, + 3EEA4F141BECDCD6008A7F35 /* icon_android.png in Resources */, + 3EEA4F3E1BECE99F008A7F35 /* icon_more@3x.png in Resources */, + 3EEA4F2B1BECE440008A7F35 /* icon_liked@2x.png in Resources */, + 3EEA4F351BECE440008A7F35 /* icon_comment.png in Resources */, + 3EEA4EF41BECC4A1008A7F35 /* Assets.xcassets in Resources */, + 3EEA4F171BECDCD6008A7F35 /* icon_ios.png in Resources */, + 3EEA4F021BECC4E8008A7F35 /* Default-667h@2x.png in Resources */, + 3EEA4F161BECDCD6008A7F35 /* icon_android@3x.png in Resources */, + 3EEA4F191BECDCD6008A7F35 /* icon_ios@3x.png in Resources */, + 3EEA4F331BECE440008A7F35 /* icon_comment@3x.png in Resources */, + 3EEA4F341BECE440008A7F35 /* icon_comment@2x.png in Resources */, + 3EEA4F321BECE440008A7F35 /* icon_like.png in Resources */, + 3EEA4F151BECDCD6008A7F35 /* icon_android@2x.png in Resources */, + 3EEA4F301BECE440008A7F35 /* icon_like@3x.png in Resources */, + 3EEA4F2C1BECE440008A7F35 /* icon_liked@3x.png in Resources */, + 3EEA4F011BECC4E8008A7F35 /* Default-568h@2x.png in Resources */, + 3EEA4F031BECC4E8008A7F35 /* Default-736h@3x.png in Resources */, + 3EEA4F3C1BECE99F008A7F35 /* icon_more.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 21F2C1D9B53F9468EAF1653F /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 852437589F1D53B9483A75DF /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + B5BD9E5609B2CB179EEE0CF4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3EEA4EE01BECC4A1008A7F35 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EEA4EEF1BECC4A1008A7F35 /* ViewController.m in Sources */, + 3EEA4EEC1BECC4A1008A7F35 /* AppDelegate.m in Sources */, + 3EEA4EE91BECC4A1008A7F35 /* main.m in Sources */, + 3EEA4F061BECC6C9008A7F35 /* Post.m in Sources */, + 3EEA4F0C1BECCA0A008A7F35 /* TextStyles.m in Sources */, + 3EEA4F381BECE775008A7F35 /* CommentsNode.m in Sources */, + 3EEA4F091BECC855008A7F35 /* PostNode.m in Sources */, + 3EEA4F1D1BECE358008A7F35 /* LikesNode.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 3EEA4EF91BECC4A1008A7F35 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 3EEA4EFA1BECC4A1008A7F35 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3EEA4EFC1BECC4A1008A7F35 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CC6F2ABE8383FAB21802C734 /* Pods-Sample.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Sample/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.AsyncDisplayKit.Sample; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3EEA4EFD1BECC4A1008A7F35 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FCCC1AD413FCA8603156ED15 /* Pods-Sample.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Sample/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 7.1; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.AsyncDisplayKit.Sample; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3EEA4EDF1BECC4A1008A7F35 /* Build configuration list for PBXProject "Sample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3EEA4EF91BECC4A1008A7F35 /* Debug */, + 3EEA4EFA1BECC4A1008A7F35 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3EEA4EFB1BECC4A1008A7F35 /* Build configuration list for PBXNativeTarget "Sample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3EEA4EFC1BECC4A1008A7F35 /* Debug */, + 3EEA4EFD1BECC4A1008A7F35 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3EEA4EDC1BECC4A1008A7F35 /* Project object */; +} diff --git a/examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..a80c038249 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/SocialAppLayout-Inverted/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme b/examples/SocialAppLayout-Inverted/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme new file mode 100644 index 0000000000..64285ed126 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/SocialAppLayout-Inverted/Sample/AppDelegate.h b/examples/SocialAppLayout-Inverted/Sample/AppDelegate.h new file mode 100644 index 0000000000..27e560aafe --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/AppDelegate.h @@ -0,0 +1,24 @@ +// +// AppDelegate.h +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/AppDelegate.m b/examples/SocialAppLayout-Inverted/Sample/AppDelegate.m new file mode 100644 index 0000000000..da7d93f4d8 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/AppDelegate.m @@ -0,0 +1,32 @@ +// +// AppDelegate.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import "AppDelegate.h" +#import "ViewController.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.backgroundColor = [UIColor whiteColor]; + self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]]; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/SocialAppLayout-Inverted/Sample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..118c98f746 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/SocialAppLayout-Inverted/Sample/CommentsNode.h b/examples/SocialAppLayout-Inverted/Sample/CommentsNode.h new file mode 100644 index 0000000000..24e39cb5b4 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/CommentsNode.h @@ -0,0 +1,24 @@ +// +// CommentsNode.h +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import + +@interface CommentsNode : ASControlNode + +- (instancetype)initWithCommentsCount:(NSInteger)comentsCount; + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/CommentsNode.m b/examples/SocialAppLayout-Inverted/Sample/CommentsNode.m new file mode 100644 index 0000000000..48d1d457ad --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/CommentsNode.m @@ -0,0 +1,70 @@ +// +// CommentsNode.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import "CommentsNode.h" +#import "TextStyles.h" + +@interface CommentsNode () +@property (nonatomic, strong) ASImageNode *iconNode; +@property (nonatomic, strong) ASTextNode *countNode; +@property (nonatomic, assign) NSInteger commentsCount; +@end + +@implementation CommentsNode + +- (instancetype)initWithCommentsCount:(NSInteger)comentsCount +{ + self = [super init]; + if (self) { + _commentsCount = comentsCount; + + _iconNode = [[ASImageNode alloc] init]; + _iconNode.image = [UIImage imageNamed:@"icon_comment.png"]; + [self addSubnode:_iconNode]; + + _countNode = [[ASTextNode alloc] init]; + if (_commentsCount > 0) { + _countNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%zd", _commentsCount] attributes:[TextStyles cellControlStyle]]; + } + [self addSubnode:_countNode]; + + // make it tappable easily + self.hitTestSlop = UIEdgeInsetsMake(-10, -10, -10, -10); + } + + return self; + +} + +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ + ASStackLayoutSpec *mainStack = + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:6.0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsCenter + children:@[_iconNode, _countNode]]; + + // Adjust size + mainStack.style.minWidth = ASDimensionMakeWithPoints(60.0); + mainStack.style.maxHeight = ASDimensionMakeWithPoints(40.0); + + return mainStack; +} + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/Default-568h@2x.png b/examples/SocialAppLayout-Inverted/Sample/Default-568h@2x.png new file mode 100644 index 0000000000..6ee80b9393 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/Default-568h@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/Default-667h@2x.png b/examples/SocialAppLayout-Inverted/Sample/Default-667h@2x.png new file mode 100644 index 0000000000..e7b975e21b Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/Default-667h@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/Default-736h@3x.png b/examples/SocialAppLayout-Inverted/Sample/Default-736h@3x.png new file mode 100644 index 0000000000..c8949cae16 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/Default-736h@3x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/Info.plist b/examples/SocialAppLayout-Inverted/Sample/Info.plist new file mode 100644 index 0000000000..ed1c9acf9b --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/SocialAppLayout-Inverted/Sample/LikesNode.h b/examples/SocialAppLayout-Inverted/Sample/LikesNode.h new file mode 100644 index 0000000000..b98cbebef6 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/LikesNode.h @@ -0,0 +1,24 @@ +// +// LikesNode.h +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import + +@interface LikesNode : ASControlNode + +- (instancetype)initWithLikesCount:(NSInteger)likesCount; + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/LikesNode.m b/examples/SocialAppLayout-Inverted/Sample/LikesNode.m new file mode 100644 index 0000000000..593d5ae5de --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/LikesNode.m @@ -0,0 +1,83 @@ +// +// LikesNode.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import "LikesNode.h" +#import "TextStyles.h" + +@interface LikesNode () +@property (nonatomic, strong) ASImageNode *iconNode; +@property (nonatomic, strong) ASTextNode *countNode; +@property (nonatomic, assign) NSInteger likesCount; +@property (nonatomic, assign) BOOL liked; +@end + +@implementation LikesNode + +- (instancetype)initWithLikesCount:(NSInteger)likesCount +{ + self = [super init]; + if (self) { + _likesCount = likesCount; + _liked = (_likesCount > 0) ? [LikesNode getYesOrNo] : NO; + + _iconNode = [[ASImageNode alloc] init]; + _iconNode.image = (_liked) ? [UIImage imageNamed:@"icon_liked.png"] : [UIImage imageNamed:@"icon_like.png"]; + [self addSubnode:_iconNode]; + + _countNode = [[ASTextNode alloc] init]; + if (_likesCount > 0) { + + NSDictionary *attributes = _liked ? [TextStyles cellControlColoredStyle] : [TextStyles cellControlStyle]; + _countNode.attributedText = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%ld", (long)_likesCount] attributes:attributes]; + + } + [self addSubnode:_countNode]; + + // make it tappable easily + self.hitTestSlop = UIEdgeInsetsMake(-10, -10, -10, -10); + } + + return self; + +} + ++ (BOOL)getYesOrNo +{ + int tmp = (arc4random() % 30)+1; + if (tmp % 5 == 0) { + return YES; + } + return NO; +} + +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ + ASStackLayoutSpec *mainStack = + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:6.0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsCenter + children:@[_iconNode, _countNode]]; + + mainStack.style.minWidth = ASDimensionMakeWithPoints(60.0); + mainStack.style.maxHeight = ASDimensionMakeWithPoints(40.0); + + return mainStack; +} + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/Post.h b/examples/SocialAppLayout-Inverted/Sample/Post.h new file mode 100644 index 0000000000..44bed0dd73 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/Post.h @@ -0,0 +1,33 @@ +// +// Post.h +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import + +@interface Post : NSObject + +@property (nonatomic, copy) NSString *username; +@property (nonatomic, copy) NSString *name; +@property (nonatomic, copy) NSString *photo; +@property (nonatomic, copy) NSString *post; +@property (nonatomic, copy) NSString *time; +@property (nonatomic, copy) NSString *media; +@property (nonatomic, assign) NSInteger via; + +@property (nonatomic, assign) NSInteger likes; +@property (nonatomic, assign) NSInteger comments; + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/Post.m b/examples/SocialAppLayout-Inverted/Sample/Post.m new file mode 100644 index 0000000000..10bf3a7623 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/Post.m @@ -0,0 +1,21 @@ +// +// Post.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import "Post.h" + +@implementation Post +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/PostNode.h b/examples/SocialAppLayout-Inverted/Sample/PostNode.h new file mode 100644 index 0000000000..6d8c62696d --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/PostNode.h @@ -0,0 +1,26 @@ +// +// PostNode.h +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import + +@class Post; + +@interface PostNode : ASCellNode + +- (instancetype)initWithPost:(Post *)post; + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/PostNode.m b/examples/SocialAppLayout-Inverted/Sample/PostNode.m new file mode 100644 index 0000000000..a40e231c05 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/PostNode.m @@ -0,0 +1,336 @@ +// +// PostNode.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import "PostNode.h" +#import "Post.h" +#import "TextStyles.h" +#import "LikesNode.h" +#import "CommentsNode.h" + +#define PostNodeDividerColor [UIColor lightGrayColor] + +@interface PostNode() + +@property (strong, nonatomic) Post *post; +@property (strong, nonatomic) ASDisplayNode *divider; +@property (strong, nonatomic) ASTextNode *nameNode; +@property (strong, nonatomic) ASTextNode *usernameNode; +@property (strong, nonatomic) ASTextNode *timeNode; +@property (strong, nonatomic) ASTextNode *postNode; +@property (strong, nonatomic) ASImageNode *viaNode; +@property (strong, nonatomic) ASNetworkImageNode *avatarNode; +@property (strong, nonatomic) ASNetworkImageNode *mediaNode; +@property (strong, nonatomic) LikesNode *likesNode; +@property (strong, nonatomic) CommentsNode *commentsNode; +@property (strong, nonatomic) ASImageNode *optionsNode; + +@end + +@implementation PostNode + +#pragma mark - Lifecycle + +- (instancetype)initWithPost:(Post *)post +{ + self = [super init]; + if (self) { + _post = post; + + // Name node + _nameNode = [[ASTextNode alloc] init]; + _nameNode.attributedText = [[NSAttributedString alloc] initWithString:_post.name attributes:[TextStyles nameStyle]]; + _nameNode.maximumNumberOfLines = 1; + [self addSubnode:_nameNode]; + + // Username node + _usernameNode = [[ASTextNode alloc] init]; + _usernameNode.attributedText = [[NSAttributedString alloc] initWithString:_post.username attributes:[TextStyles usernameStyle]]; + _usernameNode.style.flexShrink = 1.0; //if name and username don't fit to cell width, allow username shrink + _usernameNode.truncationMode = NSLineBreakByTruncatingTail; + _usernameNode.maximumNumberOfLines = 1; + [self addSubnode:_usernameNode]; + + // Time node + _timeNode = [[ASTextNode alloc] init]; + _timeNode.attributedText = [[NSAttributedString alloc] initWithString:_post.time attributes:[TextStyles timeStyle]]; + [self addSubnode:_timeNode]; + + // Post node + _postNode = [[ASTextNode alloc] init]; + + // Processing URLs in post + NSString *kLinkAttributeName = @"TextLinkAttributeName"; + + if (![_post.post isEqualToString:@""]) { + + NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:_post.post attributes:[TextStyles postStyle]]; + + NSDataDetector *urlDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil]; + + [urlDetector enumerateMatchesInString:attrString.string options:kNilOptions range:NSMakeRange(0, attrString.string.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop){ + + if (result.resultType == NSTextCheckingTypeLink) { + + NSMutableDictionary *linkAttributes = [[NSMutableDictionary alloc] initWithDictionary:[TextStyles postLinkStyle]]; + linkAttributes[kLinkAttributeName] = [NSURL URLWithString:result.URL.absoluteString]; + + [attrString addAttributes:linkAttributes range:result.range]; + + } + + }]; + + // Configure node to support tappable links + _postNode.delegate = self; + _postNode.userInteractionEnabled = YES; + _postNode.linkAttributeNames = @[ kLinkAttributeName ]; + _postNode.attributedText = attrString; + _postNode.passthroughNonlinkTouches = YES; // passes touches through when they aren't on a link + + } + + [self addSubnode:_postNode]; + + + // Media + if (![_post.media isEqualToString:@""]) { + + _mediaNode = [[ASNetworkImageNode alloc] init]; + _mediaNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor(); + _mediaNode.cornerRadius = 4.0; + _mediaNode.URL = [NSURL URLWithString:_post.media]; + _mediaNode.delegate = self; + _mediaNode.imageModificationBlock = ^UIImage *(UIImage *image) { + + UIImage *modifiedImage; + CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); + + UIGraphicsBeginImageContextWithOptions(image.size, false, [[UIScreen mainScreen] scale]); + + [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:8.0] addClip]; + [image drawInRect:rect]; + modifiedImage = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + + return modifiedImage; + + }; + [self addSubnode:_mediaNode]; + } + + // User pic + _avatarNode = [[ASNetworkImageNode alloc] init]; + _avatarNode.backgroundColor = ASDisplayNodeDefaultPlaceholderColor(); + _avatarNode.style.width = ASDimensionMakeWithPoints(44); + _avatarNode.style.height = ASDimensionMakeWithPoints(44); + _avatarNode.cornerRadius = 22.0; + _avatarNode.URL = [NSURL URLWithString:_post.photo]; + _avatarNode.imageModificationBlock = ^UIImage *(UIImage *image) { + + UIImage *modifiedImage; + CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); + + UIGraphicsBeginImageContextWithOptions(image.size, false, [[UIScreen mainScreen] scale]); + + [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:44.0] addClip]; + [image drawInRect:rect]; + modifiedImage = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + + return modifiedImage; + + }; + [self addSubnode:_avatarNode]; + + // Hairline cell separator + _divider = [[ASDisplayNode alloc] init]; + [self updateDividerColor]; + [self addSubnode:_divider]; + + // Via + if (_post.via != 0) { + _viaNode = [[ASImageNode alloc] init]; + _viaNode.image = (_post.via == 1) ? [UIImage imageNamed:@"icon_ios.png"] : [UIImage imageNamed:@"icon_android.png"]; + [self addSubnode:_viaNode]; + } + + // Bottom controls + _likesNode = [[LikesNode alloc] initWithLikesCount:_post.likes]; + [self addSubnode:_likesNode]; + + _commentsNode = [[CommentsNode alloc] initWithCommentsCount:_post.comments]; + [self addSubnode:_commentsNode]; + + _optionsNode = [[ASImageNode alloc] init]; + _optionsNode.image = [UIImage imageNamed:@"icon_more"]; + [self addSubnode:_optionsNode]; + } + return self; +} + +- (void)updateDividerColor +{ + /* + * UITableViewCell traverses through all its descendant views and adjusts their background color accordingly + * either to [UIColor clearColor], although potentially it could use the same color as the selection highlight itself. + * After selection, the same trick is performed again in reverse, putting all the backgrounds back as they used to be. + * But in our case, we don't want to have the background color disappearing so we reset it after highlighting or + * selection is done. + */ + _divider.backgroundColor = PostNodeDividerColor; +} + +#pragma mark - ASDisplayNode + +- (void)didLoad +{ + // enable highlighting now that self.layer has loaded -- see ASHighlightOverlayLayer.h + self.layer.as_allowsHighlightDrawing = YES; + + [super didLoad]; +} + +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ + // Flexible spacer between username and time + ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init]; + spacer.style.flexGrow = 1.0; + + // Horizontal stack for name, username, via icon and time + NSMutableArray *layoutSpecChildren = [@[_nameNode, _usernameNode, spacer] mutableCopy]; + if (_post.via != 0) { + [layoutSpecChildren addObject:_viaNode]; + } + [layoutSpecChildren addObject:_timeNode]; + + ASStackLayoutSpec *nameStack = + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:5.0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsCenter + children:layoutSpecChildren]; + nameStack.style.alignSelf = ASStackLayoutAlignSelfStretch; + + // bottom controls horizontal stack + ASStackLayoutSpec *controlsStack = + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:10 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsCenter + children:@[_likesNode, _commentsNode, _optionsNode]]; + + // Add more gaps for control line + controlsStack.style.spacingAfter = 3.0; + controlsStack.style.spacingBefore = 3.0; + + NSMutableArray *mainStackContent = [[NSMutableArray alloc] init]; + [mainStackContent addObject:nameStack]; + [mainStackContent addObject:_postNode]; + + + if (![_post.media isEqualToString:@""]){ + + // Only add the media node if an image is present + if (_mediaNode.image != nil) { + ASRatioLayoutSpec *imagePlace = + [ASRatioLayoutSpec + ratioLayoutSpecWithRatio:0.5 + child:_mediaNode]; + imagePlace.style.spacingAfter = 3.0; + imagePlace.style.spacingBefore = 3.0; + + [mainStackContent addObject:imagePlace]; + } + } + [mainStackContent addObject:controlsStack]; + + // Vertical spec of cell main content + ASStackLayoutSpec *contentSpec = + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical + spacing:8.0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStretch + children:mainStackContent]; + contentSpec.style.flexShrink = 1.0; + + // Horizontal spec for avatar + ASStackLayoutSpec *avatarContentSpec = + [ASStackLayoutSpec + stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal + spacing:8.0 + justifyContent:ASStackLayoutJustifyContentStart + alignItems:ASStackLayoutAlignItemsStart + children:@[_avatarNode, contentSpec]]; + + return [ASInsetLayoutSpec + insetLayoutSpecWithInsets:UIEdgeInsetsMake(10, 10, 10, 10) + child:avatarContentSpec]; + +} + +- (void)layout +{ + [super layout]; + + // Manually layout the divider. + CGFloat pixelHeight = 1.0f / [[UIScreen mainScreen] scale]; + _divider.frame = CGRectMake(0.0f, 0.0f, self.calculatedSize.width, pixelHeight); +} + +#pragma mark - ASCellNode + +- (void)setHighlighted:(BOOL)highlighted +{ + [super setHighlighted:highlighted]; + + [self updateDividerColor]; +} + +- (void)setSelected:(BOOL)selected +{ + [super setSelected:selected]; + + [self updateDividerColor]; +} + +#pragma mark - + +- (BOOL)textNode:(ASTextNode *)richTextNode shouldHighlightLinkAttribute:(NSString *)attribute value:(id)value atPoint:(CGPoint)point +{ + // Opt into link highlighting -- tap and hold the link to try it! must enable highlighting on a layer, see -didLoad + return YES; +} + +- (void)textNode:(ASTextNode *)richTextNode tappedLinkAttribute:(NSString *)attribute value:(NSURL *)URL atPoint:(CGPoint)point textRange:(NSRange)textRange +{ + // The node tapped a link, open it + [[UIApplication sharedApplication] openURL:URL]; +} + +#pragma mark - ASNetworkImageNodeDelegate methods. + +- (void)imageNode:(ASNetworkImageNode *)imageNode didLoadImage:(UIImage *)image +{ + [self setNeedsLayout]; +} + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/TextStyles.h b/examples/SocialAppLayout-Inverted/Sample/TextStyles.h new file mode 100644 index 0000000000..b8ef6780c1 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/TextStyles.h @@ -0,0 +1,31 @@ +// +// TextStyles.h +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import +#import + +@interface TextStyles : NSObject + ++ (NSDictionary *)nameStyle; ++ (NSDictionary *)usernameStyle; ++ (NSDictionary *)timeStyle; ++ (NSDictionary *)postStyle; ++ (NSDictionary *)postLinkStyle; ++ (NSDictionary *)cellControlStyle; ++ (NSDictionary *)cellControlColoredStyle; + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/TextStyles.m b/examples/SocialAppLayout-Inverted/Sample/TextStyles.m new file mode 100644 index 0000000000..8f642522b7 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/TextStyles.m @@ -0,0 +1,79 @@ +// +// TextStyles.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import "TextStyles.h" + +@implementation TextStyles + ++ (NSDictionary *)nameStyle +{ + return @{ + NSFontAttributeName : [UIFont boldSystemFontOfSize:15.0], + NSForegroundColorAttributeName: [UIColor blackColor] + }; +} + ++ (NSDictionary *)usernameStyle +{ + return @{ + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor lightGrayColor] + }; +} + ++ (NSDictionary *)timeStyle +{ + return @{ + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor grayColor] + }; +} + ++ (NSDictionary *)postStyle +{ + return @{ + NSFontAttributeName : [UIFont systemFontOfSize:15.0], + NSForegroundColorAttributeName: [UIColor blackColor] + }; +} + ++ (NSDictionary *)postLinkStyle +{ + return @{ + NSFontAttributeName : [UIFont systemFontOfSize:15.0], + NSForegroundColorAttributeName: [UIColor colorWithRed:59.0/255.0 green:89.0/255.0 blue:152.0/255.0 alpha:1.0], + NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle) + }; +} + ++ (NSDictionary *)cellControlStyle +{ + return @{ + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor lightGrayColor] + }; +} + ++ (NSDictionary *)cellControlColoredStyle +{ + return @{ + NSFontAttributeName : [UIFont systemFontOfSize:13.0], + NSForegroundColorAttributeName: [UIColor colorWithRed:59.0/255.0 green:89.0/255.0 blue:152.0/255.0 alpha:1.0] + }; +} + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/ViewController.h b/examples/SocialAppLayout-Inverted/Sample/ViewController.h new file mode 100644 index 0000000000..bfb359c6b5 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/ViewController.h @@ -0,0 +1,21 @@ +// +// ViewController.h +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import + +@interface ViewController : ASViewController +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/ViewController.m b/examples/SocialAppLayout-Inverted/Sample/ViewController.m new file mode 100644 index 0000000000..6e73b9e801 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/ViewController.m @@ -0,0 +1,166 @@ +// +// ViewController.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import "ViewController.h" +#import "Post.h" +#import "PostNode.h" + +#import +#import + +#include + +@interface ViewController () + +@property (nonatomic, strong) ASTableNode *tableNode; +@property (nonatomic, strong) NSMutableArray *socialAppDataSource; + +@end + +#pragma mark - Lifecycle + +@implementation ViewController + +- (instancetype)init +{ + _tableNode = [[ASTableNode alloc] initWithStyle:UITableViewStylePlain]; + _tableNode.inverted = YES; + self = [super initWithNode:_tableNode]; + + + if (self) { + + _tableNode.delegate = self; + _tableNode.dataSource = self; + self.title = @"Timeline"; + + [self createSocialAppDataSource]; + } + + return self; +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + CGFloat inset = [self topBarsHeight]; + self.tableNode.view.contentInset = UIEdgeInsetsMake(-inset, 0, inset, 0); + self.tableNode.view.scrollIndicatorInsets = UIEdgeInsetsMake(-inset, 0, inset, 0); +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // SocialAppNode has its own separator + self.tableNode.view.separatorStyle = UITableViewCellSeparatorStyleNone; +} + +- (CGFloat)topBarsHeight +{ + // No need to adjust if the edge isn't available + if ((self.edgesForExtendedLayout & UIRectEdgeTop) == 0) { + return 0.0; + } + return CGRectGetHeight(self.navigationController.navigationBar.frame) + CGRectGetHeight([UIApplication sharedApplication].statusBarFrame); +} + + +#pragma mark - Data Model + +- (void)createSocialAppDataSource +{ + _socialAppDataSource = [[NSMutableArray alloc] init]; + + Post *newPost = [[Post alloc] init]; + newPost.name = @"Apple Guy"; + newPost.username = @"@appleguy"; + newPost.photo = @"https://avatars1.githubusercontent.com/u/565251?v=3&s=96"; + newPost.post = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."; + newPost.time = @"3s"; + newPost.media = @""; + newPost.via = 0; + newPost.likes = arc4random_uniform(74); + newPost.comments = arc4random_uniform(40); + [_socialAppDataSource addObject:newPost]; + + newPost = [[Post alloc] init]; + newPost.name = @"Huy Nguyen"; + newPost.username = @"@nguyenhuy"; + newPost.photo = @"https://avatars2.githubusercontent.com/u/587874?v=3&s=96"; + newPost.post = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + newPost.time = @"1m"; + newPost.media = @""; + newPost.via = 1; + newPost.likes = arc4random_uniform(74); + newPost.comments = arc4random_uniform(40); + [_socialAppDataSource addObject:newPost]; + + newPost = [[Post alloc] init]; + newPost.name = @"Alex Long Name"; + newPost.username = @"@veryyyylongusername"; + newPost.photo = @"https://avatars1.githubusercontent.com/u/8086633?v=3&s=96"; + newPost.post = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + newPost.time = @"3:02"; + newPost.media = @"http://www.ngmag.ru/upload/iblock/f93/f9390efc34151456598077c1ba44a94d.jpg"; + newPost.via = 2; + newPost.likes = arc4random_uniform(74); + newPost.comments = arc4random_uniform(40); + [_socialAppDataSource addObject:newPost]; + + newPost = [[Post alloc] init]; + newPost.name = @"Vitaly Baev"; + newPost.username = @"@vitalybaev"; + newPost.photo = @"https://avatars0.githubusercontent.com/u/724423?v=3&s=96"; + newPost.post = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. https://github.com/facebook/AsyncDisplayKit Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + newPost.time = @"yesterday"; + newPost.media = @""; + newPost.via = 1; + newPost.likes = arc4random_uniform(74); + newPost.comments = arc4random_uniform(40); + [_socialAppDataSource addObject:newPost]; +} + +#pragma mark - ASTableNode + +- (ASCellNodeBlock)tableNode:(ASTableNode *)tableNode nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath +{ + Post *post = self.socialAppDataSource[indexPath.row]; + return ^{ + return [[PostNode alloc] initWithPost:post]; + }; +} + +- (NSInteger)tableNode:(ASTableNode *)tableNode numberOfRowsInSection:(NSInteger)section +{ + return self.socialAppDataSource.count; +} + +- (void)tableNode:(ASTableNode *)tableNode didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + PostNode *postNode = (PostNode *)[_tableNode nodeForRowAtIndexPath:indexPath]; + Post *post = self.socialAppDataSource[indexPath.row]; + + BOOL shouldRasterize = postNode.shouldRasterizeDescendants; + shouldRasterize = !shouldRasterize; + postNode.shouldRasterizeDescendants = shouldRasterize; + + NSLog(@"%@ rasterization for %@'s post: %@", shouldRasterize ? @"Enabling" : @"Disabling", post.name, postNode); + + [tableNode deselectRowAtIndexPath:indexPath animated:YES]; +} + +@end diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_android.png b/examples/SocialAppLayout-Inverted/Sample/icon_android.png new file mode 100644 index 0000000000..6d30985339 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_android.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_android@2x.png b/examples/SocialAppLayout-Inverted/Sample/icon_android@2x.png new file mode 100644 index 0000000000..c0dd2f5977 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_android@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_android@3x.png b/examples/SocialAppLayout-Inverted/Sample/icon_android@3x.png new file mode 100644 index 0000000000..d3e83e9334 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_android@3x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_comment.png b/examples/SocialAppLayout-Inverted/Sample/icon_comment.png new file mode 100644 index 0000000000..59ccfe43c1 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_comment.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_comment@2x.png b/examples/SocialAppLayout-Inverted/Sample/icon_comment@2x.png new file mode 100644 index 0000000000..bedd0593c0 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_comment@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_comment@3x.png b/examples/SocialAppLayout-Inverted/Sample/icon_comment@3x.png new file mode 100644 index 0000000000..eb8a0d7660 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_comment@3x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_ios.png b/examples/SocialAppLayout-Inverted/Sample/icon_ios.png new file mode 100644 index 0000000000..0cd417d446 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_ios.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_ios@2x.png b/examples/SocialAppLayout-Inverted/Sample/icon_ios@2x.png new file mode 100644 index 0000000000..f73561fd09 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_ios@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_ios@3x.png b/examples/SocialAppLayout-Inverted/Sample/icon_ios@3x.png new file mode 100644 index 0000000000..35d2bb2b37 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_ios@3x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_like.png b/examples/SocialAppLayout-Inverted/Sample/icon_like.png new file mode 100644 index 0000000000..43110b9d59 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_like.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_like@2x.png b/examples/SocialAppLayout-Inverted/Sample/icon_like@2x.png new file mode 100644 index 0000000000..1b535d748b Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_like@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_like@3x.png b/examples/SocialAppLayout-Inverted/Sample/icon_like@3x.png new file mode 100644 index 0000000000..8c80507335 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_like@3x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_liked.png b/examples/SocialAppLayout-Inverted/Sample/icon_liked.png new file mode 100644 index 0000000000..b1c1ade901 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_liked.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_liked@2x.png b/examples/SocialAppLayout-Inverted/Sample/icon_liked@2x.png new file mode 100644 index 0000000000..d9dc5988ea Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_liked@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_liked@3x.png b/examples/SocialAppLayout-Inverted/Sample/icon_liked@3x.png new file mode 100644 index 0000000000..00578ac63e Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_liked@3x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_more.png b/examples/SocialAppLayout-Inverted/Sample/icon_more.png new file mode 100644 index 0000000000..013126d291 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_more.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_more@2x.png b/examples/SocialAppLayout-Inverted/Sample/icon_more@2x.png new file mode 100644 index 0000000000..3d183df436 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_more@2x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_more@3x.png b/examples/SocialAppLayout-Inverted/Sample/icon_more@3x.png new file mode 100644 index 0000000000..d5f829ab11 Binary files /dev/null and b/examples/SocialAppLayout-Inverted/Sample/icon_more@3x.png differ diff --git a/examples/SocialAppLayout-Inverted/Sample/main.m b/examples/SocialAppLayout-Inverted/Sample/main.m new file mode 100644 index 0000000000..791ef4b743 --- /dev/null +++ b/examples/SocialAppLayout-Inverted/Sample/main.m @@ -0,0 +1,25 @@ +// +// main.m +// Sample +// +// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. An additional grant +// of patent rights can be found in the PATENTS file in the same directory. +// +// 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 +// FACEBOOK 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. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +}