From b3be451486eb7f78bd5842790f208ea114de4f7e Mon Sep 17 00:00:00 2001 From: aaronschubert0 Date: Fri, 20 Jan 2017 02:16:01 +0000 Subject: [PATCH] [ASTableNode/ASCollectionNode] Inversion (#2891) * Add inverted property to ASTableNode * Add inverted property to ASCollectionNode * Add example * De-inform data controller and use different CATransform3D * Add logic to pending state * Add accessor for inverted property --- AsyncDisplayKit/ASCollectionNode.h | 6 + AsyncDisplayKit/ASCollectionNode.mm | 23 + AsyncDisplayKit/ASCollectionView.h | 5 + AsyncDisplayKit/ASCollectionView.mm | 3 + AsyncDisplayKit/ASTableNode.h | 5 + AsyncDisplayKit/ASTableNode.mm | 23 + AsyncDisplayKit/ASTableView.h | 5 + AsyncDisplayKit/ASTableView.mm | 3 + AsyncDisplayKit/Details/ASDataController.mm | 1 - .../Private/ASDisplayNode+UIViewBridge.mm | 16 +- AsyncDisplayKit/Private/_ASPendingState.mm | 8 +- examples/SocialAppLayout-Inverted/Podfile | 5 + .../Sample.xcodeproj/project.pbxproj | 484 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Sample.xcscheme | 91 ++++ .../Sample/AppDelegate.h | 24 + .../Sample/AppDelegate.m | 32 ++ .../AppIcon.appiconset/Contents.json | 38 ++ .../Sample/CommentsNode.h | 24 + .../Sample/CommentsNode.m | 70 +++ .../Sample/Default-568h@2x.png | Bin 0 -> 17520 bytes .../Sample/Default-667h@2x.png | Bin 0 -> 18314 bytes .../Sample/Default-736h@3x.png | Bin 0 -> 23380 bytes .../Sample/Info.plist | 41 ++ .../Sample/LikesNode.h | 24 + .../Sample/LikesNode.m | 83 +++ .../SocialAppLayout-Inverted/Sample/Post.h | 33 ++ .../SocialAppLayout-Inverted/Sample/Post.m | 21 + .../Sample/PostNode.h | 26 + .../Sample/PostNode.m | 336 ++++++++++++ .../Sample/TextStyles.h | 31 ++ .../Sample/TextStyles.m | 79 +++ .../Sample/ViewController.h | 21 + .../Sample/ViewController.m | 166 ++++++ .../Sample/icon_android.png | Bin 0 -> 387 bytes .../Sample/icon_android@2x.png | Bin 0 -> 733 bytes .../Sample/icon_android@3x.png | Bin 0 -> 1080 bytes .../Sample/icon_comment.png | Bin 0 -> 262 bytes .../Sample/icon_comment@2x.png | Bin 0 -> 358 bytes .../Sample/icon_comment@3x.png | Bin 0 -> 490 bytes .../Sample/icon_ios.png | Bin 0 -> 340 bytes .../Sample/icon_ios@2x.png | Bin 0 -> 706 bytes .../Sample/icon_ios@3x.png | Bin 0 -> 1052 bytes .../Sample/icon_like.png | Bin 0 -> 348 bytes .../Sample/icon_like@2x.png | Bin 0 -> 728 bytes .../Sample/icon_like@3x.png | Bin 0 -> 1071 bytes .../Sample/icon_liked.png | Bin 0 -> 400 bytes .../Sample/icon_liked@2x.png | Bin 0 -> 781 bytes .../Sample/icon_liked@3x.png | Bin 0 -> 1208 bytes .../Sample/icon_more.png | Bin 0 -> 205 bytes .../Sample/icon_more@2x.png | Bin 0 -> 418 bytes .../Sample/icon_more@3x.png | Bin 0 -> 594 bytes .../SocialAppLayout-Inverted/Sample/main.m | 25 + 53 files changed, 1746 insertions(+), 13 deletions(-) create mode 100644 examples/SocialAppLayout-Inverted/Podfile create mode 100644 examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.pbxproj create mode 100644 examples/SocialAppLayout-Inverted/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 examples/SocialAppLayout-Inverted/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme create mode 100644 examples/SocialAppLayout-Inverted/Sample/AppDelegate.h create mode 100644 examples/SocialAppLayout-Inverted/Sample/AppDelegate.m create mode 100644 examples/SocialAppLayout-Inverted/Sample/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/SocialAppLayout-Inverted/Sample/CommentsNode.h create mode 100644 examples/SocialAppLayout-Inverted/Sample/CommentsNode.m create mode 100644 examples/SocialAppLayout-Inverted/Sample/Default-568h@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/Default-667h@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/Default-736h@3x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/Info.plist create mode 100644 examples/SocialAppLayout-Inverted/Sample/LikesNode.h create mode 100644 examples/SocialAppLayout-Inverted/Sample/LikesNode.m create mode 100644 examples/SocialAppLayout-Inverted/Sample/Post.h create mode 100644 examples/SocialAppLayout-Inverted/Sample/Post.m create mode 100644 examples/SocialAppLayout-Inverted/Sample/PostNode.h create mode 100644 examples/SocialAppLayout-Inverted/Sample/PostNode.m create mode 100644 examples/SocialAppLayout-Inverted/Sample/TextStyles.h create mode 100644 examples/SocialAppLayout-Inverted/Sample/TextStyles.m create mode 100644 examples/SocialAppLayout-Inverted/Sample/ViewController.h create mode 100644 examples/SocialAppLayout-Inverted/Sample/ViewController.m create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_android.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_android@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_android@3x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_comment.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_comment@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_comment@3x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_ios.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_ios@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_ios@3x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_like.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_like@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_like@3x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_liked.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_liked@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_liked@3x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_more.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_more@2x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/icon_more@3x.png create mode 100644 examples/SocialAppLayout-Inverted/Sample/main.m 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 0000000000000000000000000000000000000000..6ee80b93937cd9dd79502629b14fe09aa03cacc2 GIT binary patch literal 17520 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 E06EB-U;qFB literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c8949cae16a4217842bd8ad813422c6b02e7cafa GIT binary patch literal 23380 zcmeI3&2QsG7{;dvp`~agBn}`rU}c2_5{^Co*u*CBswBI#5^1Zpi0)~3Y)@Ki6WiGC zChY|TCvFHXE5u>%NL;wV0fEGo^J@PC5E5KCaDuU&4|kFdg zdhMfNZ$I1by=i;VuulBQrS}<*{ybMEgw+Y z?`=z+D4~*BH)T)7hSad?*u+K?zba`e))iG(ur6cGRxKNw(&STfR@qT2@%#2p_u6DQ z7PV`KSr*%hG8&EQBfTCa2MV?4Y7lsEkRh;JT_T6Zzgu6CWjm;?#Ukp#wUkVU{u-UaE@^ zqby1fqcet_rOzCg%}K8}8++;b4u?yJPP41G8G;GYrOI^gIHt-DO{1g4qgQXUOS!b{ z>a(CfpPW-pdFIS>r{mxZS)M6n#Zo9|sKu_;?j)3CQL-0B1E*YN+f#&6rz5@GBVG{Z zNMC6weE<1m&#h>eWYl4c(U7q!V`EQKZH#RestsFJD<)-6&Z8IkLH~G(hhf@Aqv}!V z$$PNP%ca`4;^TXEKT3uqbAll`ph_Gbw3K;crRQu(*_~(*CG51Qqqmf0%@tL# z%OtV!#5ekuMW}3fo+cYjqbZZ7=E~GCvFmv%we)@gvDd507p%LH zca(3HiM7wHU9)NG4c*OMb=lB-OLlervW%Ms#tqVRUEP{mSL6%UTS>sm92r#lFw}aGvc-8^S+s2F7KLn=zH_>DnivE{L5fL|(tNwMYt#KUt6;MNm1~M^YZEUo zWsaBc2I{wzQ?2vUnkgr;U~vM^N4fN`$j=^QbVx(dhAOR!UT2%6Q9m1zgsvU1HSw1l zy|g^7;k{c*UiSyVzc33ax&2^sKn+c6P*;_G^K!n@JzsX48kQ}r_EkzOqv5;LIsT_} zU}&~ED@gy*9L(3RcSynm>O0ExvZf7>(zKng_C46vIdva-)Tgc7gQrX3w1O{|&Q|{L zV6(EzN&qR!9d0QLZSw_F_TSIT=isR5-_TU{QE>i$BCV!*>25)XkQ{H}i_^U`z-5-GJRH)BFa2HG_>+sQA=U>Gio()6`~F zT1ic$<#bgZor~I8wz3Cv_M1SN{U}%{tFv3r!#tQ@)5CP-ykHOxh&TjXVm@3JaB)Dy zA>b18;j(~>10oIqmzWQi1za2uaR|7?e7G#&;(&-lz$NCxWdRolL>vMxF&{1qxHur< z5O9h4a9O~`0TG9QOU#GM0xk}SI0Rf`K3o=XaX`c&;1cuUvVe;NA`StUm=Bi)TpSQ_ z2)M+2xGdn}fQUoDCFa9r0T%~E90D#eA1({HI3VH>aEbYFS-`~s5r=?F%!kVYE)Iw| z1YBZ1To!O~K*S;767%7*fQthn4gr^#50?d891w9R#I-tq&6bAj-P#d*iT2)B=M(k< zuH>!n^bk6E38D8sKf00e*l5C8%|00;m9AOHk_01yBIKmZ5;0U!VbfB+Bx0zd!= l00AHX1c1Q*gn;t`y7MJkdHVCOto({Mu5Na}c>U)4e*&NtopJyG literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..6d309853390288a65acdc179cab3d2d3dfe18bc4 GIT binary patch literal 387 zcmV-}0et?6P)52FJxc>Y5Qg7b54jXVLAy?ZRZe+L%>y?wdn zt9nUiG3(7toLEHJ!1sNZder)0Djg`tsrHXhAo;53j%8xl&E)ooc#?pJu*h^ngoRXQ zc+QiDxN6-x0D!A3!jCdo`XHyMZ#yYfOf z-+6s=&o^^#06bPwpE@0n#{(W|c>eP3=EP*C*DJ4iC1gRy1MT5~N2%1U7A+V9qAiGI zB8ZQlVEKg){R5PpzwFiTO)QBx*&EWDuK+?5ATo#b0|-MP2SB4)(dK8DarG)yD)Gdd zbdLZr0>n&+8W$;&&`-`;u`irI80(BoDHI^oz_Zus4ng7}Gq&)qPN9_jYK=*7f(VD0 zbSn`&X1SWxnkp$YO$;$<&?;nmn*;>Zv3!X42q09fLD&}3f|nRyw|sk5?U)mX>?H3f z%;as3Ujf@$@{P7jK$V_yuxiI>%Cjaj+D-LXfw-jBX=9V=V?u~?Qp)@JZ*!w0#9*y4 z)JC_DpV?0&_2~RP{H#obhgNA!LrPqC(enCEI_X~uX8 zXti4T%PQJBXlj;d>(F|cMG2X?_0OlSNn0KKPwZ&&@1)?fK2v-Q!L0MR2EbAdzw&36 zFSpJJl!fC&G;G-h_?(u*(Z~-|!cmfRHD}Oy*U`N*G2w6YfW&t1h&WGS;L^A+8Z}s& z@2d;y!U)!hb1n4}A_;WTM|hEtI{0SWSFZlR*Q8#;wBNb$2%d6$RvK{4#mbILiq*++ zefkU{J}AbB?((R87EbD!C*0LzVFToW?#`V_3#-c|g_`^uf9;7`>qUFVtha;t9<1Pk zS;2O3*{UzkNzdu8M#6jc-T=b(LLP3~3Bxc3eVVq+f2PUqu3hi!xN3g`F&f^9(E6h7y^nKEsZB8CA?s)?NrW(L}bUG$HV*=SM%F-Tmv zVnL9^jR_k!EDakIgfV^kI6(WX#O(WWUxs0uM%b=$2GQ z`MiPnQ97LtEeYMZpUxFp5X6D(!atYXt(G*n#Cmh1X5lSC5S_bm`A|6eY`37$%P8aq zAh8;Vra<6TS*Fvy9Wiq(H+e#meXutfKkJRUsP*+^%G8=God`FsnrK}A+yS08LnVDK zq@uX^EJhe%JXiP|2!1VHzw(>%^D}%^VlC*t4N^Qqet zV`kxfPT(j5H8b*MBABiN`a7pEgNWRe#;FlAzq^h-cqTD!PQJ@vs{9-urllns~JFaQUKvxStKkCGd1%AYg2XGBBjYX%A{8w3iidJ@tCLoab+ zuQ~b=gIbNLSd#5;Gp+^0m^ySp~U zzjE^Scpcd1^Js!(s!kZ(_`vl_iHpoG> z%c<=-vcBcxfHS$+ortNu2F9}a9Uw%CY&zYuIra_mKJW>5?;fS()}6OXr4Fn3=Ox}5 z=aekCL1(%WvCdI*@=by8xyF?s_X=KnuWJFnw}=sH7|`>FK{>{*YFs4TCHV0hYlJA9 zs^`J;REv+$vw0)Xu`~GuEw+t?lhaXZK*Fy_+`v zQl2ZtNy?qFY{k2ht;3Z=4PRKY976p)lF{FpxW<7_>R^tIc_SK?+8`)Ogszy5NxYFv zmbgK3K_#GY__RLZhUb`sGPcRy!{of;A8<&1pdW1u4!YrRb9#@HnM~8#@R}$1p7~d` zr6k%fi`Jl)8Bc|d=o4B+MsU_DmiuRBjMBhB+k&=pq8_L1Me`klVofFV44WcMt7naR& zwp#DS`${5}O3m|r|E&h%p9zZdQ2Ig773B}#mlbkbNJwAYX6ur=OH?E9tt=9Ww(R3* y>j>e~o@A_`b()UkF7yj2wgb|c?qr+q58?m(Crm4Qu2bs(0000t- literal 0 HcmV?d00001 diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_comment.png b/examples/SocialAppLayout-Inverted/Sample/icon_comment.png new file mode 100644 index 0000000000000000000000000000000000000000..59ccfe43c18341e7fa5c2420d081ce7a9965a8a6 GIT binary patch literal 262 zcmV+h0r~!kP)s`;yoHi%vLVPf zj-jxCEtFX z^eLrb_RIM0Y#1B=4$iCIOOHN=WdqJJ##7lWbAVFH3k;+C*V+I>2z$Ex7PDsgc6vj7 zL7>)p^xpT>sEHge0)#jZ8fqZYFiL8pwf4w4KS19M11blgZax_B1o&V`+b^diUH||9 M07*qoM6N<$f`g7|*#H0l literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..bedd0593c0fdcabc71d10903de2fc35cd4a5c6d7 GIT binary patch literal 358 zcmV-s0h#`ZP)+HhKi{46X

0@SR-LF zxM117MTz$J@mo1Lm`Fo#C*UEtGq4VK3fAG&cUmasZ^Soe1yM}ZI{*Lx07*qoM6N<$ Ef@C$A8~^|S literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..eb8a0d76608a0172249c261ce4bfea40bf3d2db9 GIT binary patch literal 490 zcmVJaY_@R|yi1_t9PwaYBaZgFB8DJ8<;V}}z1ppW73ACvmN2Zwby zC0na{PK?l=4c^H|r*~F(J~;8LKU==4s%NFt#hyS<$M0R&-GnqeFg367V;B-No4yJW zT7?LmL}(s#zWeC3Z--ewI?Yb_?xWMb9cFzIPScCgCj;5^BA{uFxUqrd9Gh3umPB8< z;E?^V!!J$KJhxS_`}wiNl2e9TYI`Ew!A7vF9KrthRaUx_%>KY`lvI9@9n` z?CMa$mYN91t(-RA(Sg6D|A6jk7wOI%hfBkAVjPJp>O1 gdI*m5U;@+OH%Zil2MrVR@c;k-07*qoM6N<$f?^5SA^-pY literal 0 HcmV?d00001 diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_ios.png b/examples/SocialAppLayout-Inverted/Sample/icon_ios.png new file mode 100644 index 0000000000000000000000000000000000000000..0cd417d4469db06413c9ba5ce514af3fe1c7abc2 GIT binary patch literal 340 zcmV-a0jvIrP)+%)s}=G$d=fQ+i%HKuE}Rk^4)XVY;Z z4gWd|zJCgle*d*?Q~oEOSX)fscpQ(2$k_*Z;Ee`jik=eAD2mMTT6tgdItU+vs^%e* z^V$s{S6%6?^3t|;4Y8*%vqaFKds|dT%9+M5bZ|R!rP8w@5#)(Q?u5I7rlAUq9NLDAkRtdOcoB(6FM@~ofuaZTg9TAj+Gs&dJeW`s?WI-;R_l_@8)sIxZg4}hnag`K z^PAuMy^nc9c(i<}d^}&QOi#TnPq>x(-GXj0UDy5E=Ixh3z=!}L5b=r|PPzr%V%nx{ zXDu>HB8so3TE69mqqSByy;uxu5S%B%2%{C^=~Ner-toK!zx-y&oM5(7_&$Wq1$ zkA}41NGcJZ^yhLppTyt|0MRZPZ^c9qH5MVaCiWa9vH_2Z8sKy^XAbnluUUjX0jC&-wd#}R9Wsh(Qj7xm2qZQW?O*c~{T?vH=62oENrAL(sgbjPh8 zB{2(2OSN;1vg~hH>viP0t+3DH691EC461CpXKMq|=0Oc&KI z+C>wM(SN`de#DebS51>Py0G;-ZcLjrEDS~kKWY;PJ5a>YR%#HV@*z4Oymyc14&2F` z#~UEy8}8=Zd(OGP-#zD@`|%KbY8{bCS-DaAH6iXnfQhiVcE@bcf!U1nwRJ~hTbb-6 zAXKshBDyly-1jE#iVl1sfX)J9P?HhhpSqt*z87(KPk)U7af&0&kSZbq`$8^4trxnJ zk3_?0XVTKFxkQ&Ynbr5QbRL7ei8~_$s}S*X7v@kLlKWgb&tcxgB>~v%MC5{s@wj!1 zX+Cr6bM^Bk<^rlngA)BuBoDuck8TKmxMm<1ky}4oabZ_)?`p#iRFlE=lC&Q-eYE~x z4UkB^{3K}0ewkhb-i$u@1VDVle!KXaFL(M+_xpk5v9K9B!(-C+EMf-P zh#)TUo?N9Ja!HQn3ELJU!c@w0IZo>ds2lD0F3!-fQe}v5-G8tRg!r9Fi{`+{-%QkN zjacE9mYUb;Z>+Wk79`G+!(nFN<2@zKwkP4kuV zR+U>Rpg6`kH|8-tFBh(d|HiEeb9;UL8x0@?1-~jJX_|=SK_{uwajJ2nUPVD9(W9o? z&~I*RMcm+4`a8y}UU-7{VY!#VFCFjSAulY!M@g}l!7m--FY>|?2sGhk@Jq*qTjhl% zxYP%|41VeOyx*!Gf^IyH7}Y&mxQ0+x9$fUTn}8#h-EO7dV=l0x*YEXJJ8=a{yyjFC zqR&}f94IR4xDokhoyO;H4}7P_9`m-U)XKt18kdp|-A|1DtS$+zcv6@20yJDAg!rMZ zWGUYd+)|cxf?pTb0x)xo)Ty3BY2w!Un#Y{;a|=N%iP{xUnpkygNryS-3DqxHBe>RF z8|qN_8RAWKp%_X!UN};kv_S6H_!(lQh$Ke8~xqGC=3`I3&7V+N3#>td5 z`6XAtOYPu?RKKkq7f)wpQ|;p!ZR(k8T;Vt9j5BtI^BfAUo1Tfc@aeY3HDgZKtcbOt z$*jI@gWbZVpGl3f@n;xepdY0rH`|l6B0l^iNXb+cNZQR&{lPX{V@&&>NhHTx-K5Iq z8L^)H)7`tl+M@DCG+;eScr-EyH+Sv~CAHlxJEPGLilMkckSvoH-D+-F_tfp9$L|18 WvP!+O%tM<10000iM4l literal 0 HcmV?d00001 diff --git a/examples/SocialAppLayout-Inverted/Sample/icon_like.png b/examples/SocialAppLayout-Inverted/Sample/icon_like.png new file mode 100644 index 0000000000000000000000000000000000000000..43110b9d598d3816a1a382d9af0a3786197278e4 GIT binary patch literal 348 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 LNkvXXu0mjf&&hF+ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..00578ac63ef82f5d64bf1653573fd41f74cf0b0a GIT binary patch literal 1208 zcmV;p1V{UcP)GDPLq$`6uxp}G z5F*kI`yed}Dg+UH(4syVHmS7G7n_YM#Ggd8VvyS1)rTnBG*$ahYa+Tx6%!PrJ99i| zbl2JJWOrtqaqNX;?mhSXd~@b-@10ozIa;;9 z6_j5tg@c!KxXGBBTi5)#1oAraH48vYL%i9_>D>^jxeWHzt*) zSR@!9sg()s_sc$M;ZC~SCi;^{D(4*|b_@<-!yjFZk5anj%R(O)jTb-BlUkLMnZ6<@ z^ptl;)$@BG5>ZliY3Rzz%^!>@tvExEYC&q!))nEO!6CJh!CwJOJ(PgywtT%dqLS<$ z{`=~Zo}R-mSd@PBAC^|^eQRL$NPtB}(huC#u5SsfxuirgANRRwnfBF%mQ(4TcqMY? zKV|0_CE;slyuJ2<>WXN%@uc9g7+YF#hiY!JqXFD;cJJA(E7PPgpH{5?p8#_jrZBHW zz$@KJic4OJR}uoNTypPKid zGp!l*^ns*b7S3+ZbR%+BS=p}9!xeqtS*4yC_w82QZ&%@(&WsQnY>xDSqaG@JDw4;H5AORo9MlmnR8_0|+Uu{c0A^%KSFBnxH>H9vy#%O!s$f!CdCmez1Sk<*H zHS|FuLfx?jv7f0b`e|$KG?=q2atxXy&s)>{1<3L#s+6J>2_4o3K~cUkI<2L2tX>_3 z=HPQ{n?I9NI6)cy&e#QY`6?zK#qG8~eHcB(eheEuJop zAr^wk2@9&lC0<%LZOTI4tb5Y=c5EH{26}u^B>!#@e-NWGN>gTe~DWM4f DckD*S literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..3d183df436d2095e259c66891259e9f4c47fc33e GIT binary patch literal 418 zcmV;T0bTxyP)uO4$~U-i;%;9n9SwNXiFWtNzlQ=2m2K-4E1OE#jIUN!?#Fr3vr;DS9kQ>{!{m^}MUrf&F;u`*> zadjW9%?{7i@X??!0ahDuf?@-1!W7L^ z6U!{iZt+9Et7>)9kQ7C6qwas5G_5ocI!-yl^t^r_;>$1$KQV1H5SM7W!~Q_L#yRzU z|5JHQUG1E=f24{7kDE!xdcr2qf` M07*qoM6N<$f($&ev;Y7A literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d5f829ab1145e76c80314eb46624f298069fa243 GIT binary patch literal 594 zcmeAS@N?(olHy`uVBq!ia0vp^Hb88~!3HE}r~eWGQY`6?zK#qG8~eHcB(gFvFmZai zIEG}fzMZz;i`h}&SaEh!V@cV!Ft!|(&QOJEnmIh0SG1IVG3;wyYNq5CV14wE($Yo| zN8t_K3LMkVsdKn2vP?guoAcn`nP#UH|*&7TT4hOOQ@$8UN5$$DcC?|c4-9~P{S z(5Yj4`Z!6b{%G3DkXJT28|N&)(-!n<-OU`epW8QB26m_FvmKO@x=vpNp5NHEw`M5CWr2Nwf{@kwwJRLHp)LO`suwOU9-L_ zXST~~TUArrdzYr~GFqpeYwIUGVfq!1Emc~czOhd~|72ga=lWH_zpoPvEILoHFZ&U2 z@czvMO9WGT>lq9eeRN*=|B0+zuUosx!{nB~rz>pMP4Qa#p2Iid)MIDYD~l|TOBv00 zx<&QV{9hN?Wp!Vw<;7gL{j2SMdc*Q23yuZ`9O%Ftfgh~AKd(y7dc2Dhm`E5rUHx3v IIVCg!02AH=5C8xG literal 0 HcmV?d00001 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])); + } +}