mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-04-01 12:23:20 +08:00
example
This commit is contained in:
@@ -14,6 +14,11 @@
|
||||
5791C5525B690FA54F26ACE8 /* libPods-Sample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A2092CAF5607B3863A3700A2 /* libPods-Sample.a */; };
|
||||
6C2C82AC19EE274300767484 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AA19EE274300767484 /* Default-667h@2x.png */; };
|
||||
6C2C82AD19EE274300767484 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6C2C82AB19EE274300767484 /* Default-736h@3x.png */; };
|
||||
8B0768B81CE7AD03002E1453 /* VideoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768B71CE7AD03002E1453 /* VideoModel.m */; };
|
||||
8B0768BC1CE7B091002E1453 /* VideoContentCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768BB1CE7B091002E1453 /* VideoContentCell.m */; };
|
||||
8B0768BF1CE7C5A1002E1453 /* WindowWithStatusBarUnderlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768BE1CE7C5A1002E1453 /* WindowWithStatusBarUnderlay.m */; };
|
||||
8B0768C51CE7C707002E1453 /* Utilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768C41CE7C707002E1453 /* Utilities.m */; };
|
||||
8B0768C91CE7C889002E1453 /* VideoFeedNodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768C81CE7C889002E1453 /* VideoFeedNodeController.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@@ -27,6 +32,16 @@
|
||||
05E2128C19D4DB510098F589 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||
6C2C82AA19EE274300767484 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = SOURCE_ROOT; };
|
||||
6C2C82AB19EE274300767484 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = SOURCE_ROOT; };
|
||||
8B0768B61CE7AD03002E1453 /* VideoModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoModel.h; sourceTree = "<group>"; };
|
||||
8B0768B71CE7AD03002E1453 /* VideoModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoModel.m; sourceTree = "<group>"; };
|
||||
8B0768BA1CE7B091002E1453 /* VideoContentCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoContentCell.h; sourceTree = "<group>"; };
|
||||
8B0768BB1CE7B091002E1453 /* VideoContentCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoContentCell.m; sourceTree = "<group>"; };
|
||||
8B0768BD1CE7C5A1002E1453 /* WindowWithStatusBarUnderlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowWithStatusBarUnderlay.h; sourceTree = "<group>"; };
|
||||
8B0768BE1CE7C5A1002E1453 /* WindowWithStatusBarUnderlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WindowWithStatusBarUnderlay.m; sourceTree = "<group>"; };
|
||||
8B0768C31CE7C707002E1453 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
|
||||
8B0768C41CE7C707002E1453 /* Utilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Utilities.m; sourceTree = "<group>"; };
|
||||
8B0768C71CE7C889002E1453 /* VideoFeedNodeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoFeedNodeController.h; sourceTree = "<group>"; };
|
||||
8B0768C81CE7C889002E1453 /* VideoFeedNodeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoFeedNodeController.m; sourceTree = "<group>"; };
|
||||
A2092CAF5607B3863A3700A2 /* libPods-Sample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Sample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CFD6AA1D30516C27DEE5602B /* 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 = "<group>"; };
|
||||
E51646FF8D3676A1D826A5AE /* 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 = "<group>"; };
|
||||
@@ -68,11 +83,16 @@
|
||||
05E2128319D4DB510098F589 /* Sample */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B0768C61CE7C85F002E1453 /* Controller */,
|
||||
8B0768B91CE7B07E002E1453 /* Nodes */,
|
||||
8B0768B51CE7ACE8002E1453 /* Models */,
|
||||
05E2128819D4DB510098F589 /* AppDelegate.h */,
|
||||
05E2128919D4DB510098F589 /* AppDelegate.m */,
|
||||
05E2128B19D4DB510098F589 /* ViewController.h */,
|
||||
05E2128C19D4DB510098F589 /* ViewController.m */,
|
||||
05E2128419D4DB510098F589 /* Supporting Files */,
|
||||
8B0768BD1CE7C5A1002E1453 /* WindowWithStatusBarUnderlay.h */,
|
||||
8B0768BE1CE7C5A1002E1453 /* WindowWithStatusBarUnderlay.m */,
|
||||
);
|
||||
path = Sample;
|
||||
sourceTree = "<group>";
|
||||
@@ -106,6 +126,35 @@
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B0768B51CE7ACE8002E1453 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B0768C31CE7C707002E1453 /* Utilities.h */,
|
||||
8B0768C41CE7C707002E1453 /* Utilities.m */,
|
||||
8B0768B61CE7AD03002E1453 /* VideoModel.h */,
|
||||
8B0768B71CE7AD03002E1453 /* VideoModel.m */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B0768B91CE7B07E002E1453 /* Nodes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B0768BA1CE7B091002E1453 /* VideoContentCell.h */,
|
||||
8B0768BB1CE7B091002E1453 /* VideoContentCell.m */,
|
||||
);
|
||||
path = Nodes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8B0768C61CE7C85F002E1453 /* Controller */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8B0768C71CE7C889002E1453 /* VideoFeedNodeController.h */,
|
||||
8B0768C81CE7C889002E1453 /* VideoFeedNodeController.m */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -228,8 +277,13 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
05E2128D19D4DB510098F589 /* ViewController.m in Sources */,
|
||||
8B0768C91CE7C889002E1453 /* VideoFeedNodeController.m in Sources */,
|
||||
05E2128A19D4DB510098F589 /* AppDelegate.m in Sources */,
|
||||
8B0768BC1CE7B091002E1453 /* VideoContentCell.m in Sources */,
|
||||
8B0768BF1CE7C5A1002E1453 /* WindowWithStatusBarUnderlay.m in Sources */,
|
||||
05E2128719D4DB510098F589 /* main.m in Sources */,
|
||||
8B0768C51CE7C707002E1453 /* Utilities.m in Sources */,
|
||||
8B0768B81CE7AD03002E1453 /* VideoModel.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -10,18 +10,36 @@
|
||||
*/
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "WindowWithStatusBarUnderlay.h"
|
||||
#import "Utilities.h"
|
||||
#import "VideoFeedNodeController.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 = [[ViewController alloc] init];
|
||||
[self.window makeKeyAndVisible];
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
|
||||
// this UIWindow subclass is neccessary to make the status bar opaque
|
||||
_window = [[WindowWithStatusBarUnderlay alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
_window.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
|
||||
VideoFeedNodeController *asdkHomeFeedVC = [[VideoFeedNodeController alloc] init];
|
||||
UINavigationController *asdkHomeFeedNavCtrl = [[UINavigationController alloc] initWithRootViewController:asdkHomeFeedVC];
|
||||
|
||||
|
||||
_window.rootViewController = asdkHomeFeedNavCtrl;
|
||||
[_window makeKeyAndVisible];
|
||||
|
||||
// Nav Bar appearance
|
||||
NSDictionary *attributes = @{NSForegroundColorAttributeName:[UIColor whiteColor]};
|
||||
[[UINavigationBar appearance] setTitleTextAttributes:attributes];
|
||||
[[UINavigationBar appearance] setBarTintColor:[UIColor lighOrangeColor]];
|
||||
[[UINavigationBar appearance] setTranslucent:NO];
|
||||
|
||||
[application setStatusBarStyle:UIStatusBarStyleLightContent];
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// VideoFeedNodeController.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Erekle on 5/15/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
@interface VideoFeedNodeController : ASViewController
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// VideoFeedNodeController.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Erekle on 5/15/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "VideoFeedNodeController.h"
|
||||
#import <AsyncDisplayKit/ASVideoPlayerNode.h>
|
||||
#import "VideoModel.h"
|
||||
#import "VideoContentCell.h"
|
||||
|
||||
@interface VideoFeedNodeController ()<ASTableDelegate, ASTableDataSource>
|
||||
|
||||
@end
|
||||
|
||||
@implementation VideoFeedNodeController
|
||||
{
|
||||
ASTableNode *_tableNode;
|
||||
NSMutableArray<VideoModel*> *_videoFeedData;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self.navigationItem.title = @"Home";
|
||||
_tableNode = [[ASTableNode alloc] init];
|
||||
_tableNode.delegate = self;
|
||||
_tableNode.dataSource = self;
|
||||
|
||||
if (!(self = [super initWithNode:_tableNode])) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
[super loadView];
|
||||
|
||||
[self generateFeedData];
|
||||
|
||||
[_tableNode.view reloadData];
|
||||
}
|
||||
|
||||
- (void)generateFeedData
|
||||
{
|
||||
_videoFeedData = [[NSMutableArray alloc] init];
|
||||
|
||||
for (int i = 0; i < 30; i++) {
|
||||
[_videoFeedData addObject:[[VideoModel alloc] init]];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - ASCollectionDelegate - ASCollectionDataSource
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
|
||||
return _videoFeedData.count;
|
||||
}
|
||||
|
||||
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
VideoModel *videoObject = [_videoFeedData objectAtIndex:indexPath.row];
|
||||
VideoContentCell *cellNode = [[VideoContentCell alloc] initWithVideoObject:videoObject];
|
||||
return cellNode;
|
||||
}
|
||||
@end
|
||||
@@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
@@ -26,11 +28,11 @@
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIStatusBarStyle</key>
|
||||
<string>UIStatusBarStyleLightContent</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
40
examples/ASDKTube/Sample/Models/Utilities.h
Normal file
40
examples/ASDKTube/Sample/Models/Utilities.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Utilities.h
|
||||
// ASDKgram
|
||||
//
|
||||
// Created by Hannah Troisi on 3/9/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
#include <UIKit/UIKit.h>
|
||||
@interface UIColor (Additions)
|
||||
|
||||
+ (UIColor *)lighOrangeColor;
|
||||
+ (UIColor *)darkBlueColor;
|
||||
+ (UIColor *)lightBlueColor;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIImage (Additions)
|
||||
|
||||
+ (UIImage *)followingButtonStretchableImageForCornerRadius:(CGFloat)cornerRadius following:(BOOL)followingEnabled;
|
||||
+ (void)downloadImageForURL:(NSURL *)url completion:(void (^)(UIImage *))block;
|
||||
|
||||
- (UIImage *)makeCircularImageWithSize:(CGSize)size;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSString (Additions)
|
||||
|
||||
// returns a user friendly elapsed time such as '50s', '6m' or '3w'
|
||||
+ (NSString *)elapsedTimeStringSinceDate:(NSString *)uploadDateString;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSAttributedString (Additions)
|
||||
|
||||
+ (NSAttributedString *)attributedStringWithString:(NSString *)string
|
||||
fontSize:(CGFloat)size
|
||||
color:(UIColor *)color
|
||||
firstWordColor:(UIColor *)firstWordColor;
|
||||
|
||||
@end
|
||||
230
examples/ASDKTube/Sample/Models/Utilities.m
Normal file
230
examples/ASDKTube/Sample/Models/Utilities.m
Normal file
@@ -0,0 +1,230 @@
|
||||
//
|
||||
// Utilities.m
|
||||
// ASDKgram
|
||||
//
|
||||
// Created by Hannah Troisi on 3/9/16.
|
||||
// Copyright © 2016 Hannah Troisi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Utilities.h"
|
||||
|
||||
#define StrokeRoundedImages 0
|
||||
|
||||
@implementation UIColor (Additions)
|
||||
|
||||
+ (UIColor *)lighOrangeColor
|
||||
{
|
||||
return [UIColor colorWithRed:1 green:0.506 blue:0.384 alpha:1];
|
||||
}
|
||||
|
||||
+ (UIColor *)darkBlueColor
|
||||
{
|
||||
return [UIColor colorWithRed:70.0/255.0 green:102.0/255.0 blue:118.0/255.0 alpha:1.0];
|
||||
}
|
||||
|
||||
+ (UIColor *)lightBlueColor
|
||||
{
|
||||
return [UIColor colorWithRed:70.0/255.0 green:165.0/255.0 blue:196.0/255.0 alpha:1.0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIImage (Additions)
|
||||
|
||||
+ (UIImage *)followingButtonStretchableImageForCornerRadius:(CGFloat)cornerRadius following:(BOOL)followingEnabled
|
||||
{
|
||||
CGSize unstretchedSize = CGSizeMake(2 * cornerRadius + 1, 2 * cornerRadius + 1);
|
||||
CGRect rect = (CGRect) {CGPointZero, unstretchedSize};
|
||||
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
|
||||
|
||||
// create a graphics context for the following status button
|
||||
UIGraphicsBeginImageContextWithOptions(unstretchedSize, NO, 0);
|
||||
|
||||
[path addClip];
|
||||
|
||||
if (followingEnabled) {
|
||||
|
||||
[[UIColor whiteColor] setFill];
|
||||
[path fill];
|
||||
|
||||
path.lineWidth = 3;
|
||||
[[UIColor lightBlueColor] setStroke];
|
||||
[path stroke];
|
||||
|
||||
} else {
|
||||
|
||||
[[UIColor lightBlueColor] setFill];
|
||||
[path fill];
|
||||
}
|
||||
|
||||
UIImage *followingBtnImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
UIImage *followingBtnImageStretchable = [followingBtnImage stretchableImageWithLeftCapWidth:cornerRadius
|
||||
topCapHeight:cornerRadius];
|
||||
return followingBtnImageStretchable;
|
||||
}
|
||||
|
||||
+ (void)downloadImageForURL:(NSURL *)url completion:(void (^)(UIImage *))block
|
||||
{
|
||||
static NSCache *simpleImageCache = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
simpleImageCache = [[NSCache alloc] init];
|
||||
simpleImageCache.countLimit = 10;
|
||||
});
|
||||
|
||||
if (!block) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if image is cached
|
||||
UIImage *image = [simpleImageCache objectForKey:url];
|
||||
if (image) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
block(image);
|
||||
});
|
||||
} else {
|
||||
// else download image
|
||||
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
|
||||
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||
if (data) {
|
||||
UIImage *image = [UIImage imageWithData:data];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
block(image);
|
||||
});
|
||||
}
|
||||
}];
|
||||
[task resume];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImage *)makeCircularImageWithSize:(CGSize)size
|
||||
{
|
||||
// make a CGRect with the image's size
|
||||
CGRect circleRect = (CGRect) {CGPointZero, size};
|
||||
|
||||
// begin the image context since we're not in a drawRect:
|
||||
UIGraphicsBeginImageContextWithOptions(circleRect.size, NO, 0);
|
||||
|
||||
// create a UIBezierPath circle
|
||||
UIBezierPath *circle = [UIBezierPath bezierPathWithRoundedRect:circleRect cornerRadius:circleRect.size.width/2];
|
||||
|
||||
// clip to the circle
|
||||
[circle addClip];
|
||||
|
||||
// draw the image in the circleRect *AFTER* the context is clipped
|
||||
[self drawInRect:circleRect];
|
||||
|
||||
// create a border (for white background pictures)
|
||||
#if StrokeRoundedImages
|
||||
circle.lineWidth = 1;
|
||||
[[UIColor darkGrayColor] set];
|
||||
[circle stroke];
|
||||
#endif
|
||||
|
||||
// get an image from the image context
|
||||
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
// end the image context since we're not in a drawRect:
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return roundedImage;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSString (Additions)
|
||||
|
||||
// Returns a user-visible date time string that corresponds to the
|
||||
// specified RFC 3339 date time string. Note that this does not handle
|
||||
// all possible RFC 3339 date time strings, just one of the most common
|
||||
// styles.
|
||||
+ (NSDate *)userVisibleDateTimeStringForRFC3339DateTimeString:(NSString *)rfc3339DateTimeString
|
||||
{
|
||||
NSDateFormatter * rfc3339DateFormatter;
|
||||
NSLocale * enUSPOSIXLocale;
|
||||
|
||||
// Convert the RFC 3339 date time string to an NSDate.
|
||||
|
||||
rfc3339DateFormatter = [[NSDateFormatter alloc] init];
|
||||
|
||||
enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
|
||||
|
||||
[rfc3339DateFormatter setLocale:enUSPOSIXLocale];
|
||||
[rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ'"];
|
||||
[rfc3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
|
||||
|
||||
return [rfc3339DateFormatter dateFromString:rfc3339DateTimeString];
|
||||
}
|
||||
|
||||
+ (NSString *)elapsedTimeStringSinceDate:(NSString *)uploadDateString
|
||||
{
|
||||
// early return if no post date string
|
||||
if (!uploadDateString)
|
||||
{
|
||||
return @"NO POST DATE";
|
||||
}
|
||||
|
||||
NSDate *postDate = [self userVisibleDateTimeStringForRFC3339DateTimeString:uploadDateString];
|
||||
|
||||
if (!postDate) {
|
||||
return @"DATE CONVERSION ERROR";
|
||||
}
|
||||
|
||||
NSDate *currentDate = [NSDate date];
|
||||
|
||||
NSCalendar *calendar = [NSCalendar currentCalendar];
|
||||
|
||||
NSUInteger seconds = [[calendar components:NSCalendarUnitSecond fromDate:postDate toDate:currentDate options:0] second];
|
||||
NSUInteger minutes = [[calendar components:NSCalendarUnitMinute fromDate:postDate toDate:currentDate options:0] minute];
|
||||
NSUInteger hours = [[calendar components:NSCalendarUnitHour fromDate:postDate toDate:currentDate options:0] hour];
|
||||
NSUInteger days = [[calendar components:NSCalendarUnitDay fromDate:postDate toDate:currentDate options:0] day];
|
||||
|
||||
NSString *elapsedTime;
|
||||
|
||||
if (days > 7) {
|
||||
elapsedTime = [NSString stringWithFormat:@"%luw", (long)ceil(days/7.0)];
|
||||
} else if (days > 0) {
|
||||
elapsedTime = [NSString stringWithFormat:@"%lud", (long)days];
|
||||
} else if (hours > 0) {
|
||||
elapsedTime = [NSString stringWithFormat:@"%luh", (long)hours];
|
||||
} else if (minutes > 0) {
|
||||
elapsedTime = [NSString stringWithFormat:@"%lum", (long)minutes];
|
||||
} else if (seconds > 0) {
|
||||
elapsedTime = [NSString stringWithFormat:@"%lus", (long)seconds];
|
||||
} else if (seconds == 0) {
|
||||
elapsedTime = @"1s";
|
||||
} else {
|
||||
elapsedTime = @"ERROR";
|
||||
}
|
||||
|
||||
return elapsedTime;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSAttributedString (Additions)
|
||||
|
||||
+ (NSAttributedString *)attributedStringWithString:(NSString *)string fontSize:(CGFloat)size
|
||||
color:(nullable UIColor *)color firstWordColor:(nullable UIColor *)firstWordColor
|
||||
{
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
|
||||
|
||||
if (string) {
|
||||
NSDictionary *attributes = @{NSForegroundColorAttributeName: color ? : [UIColor blackColor],
|
||||
NSFontAttributeName: [UIFont systemFontOfSize:size]};
|
||||
attributedString = [[NSMutableAttributedString alloc] initWithString:string];
|
||||
[attributedString addAttributes:attributes range:NSMakeRange(0, string.length)];
|
||||
|
||||
if (firstWordColor) {
|
||||
NSRange firstSpaceRange = [string rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
NSRange firstWordRange = NSMakeRange(0, firstSpaceRange.location);
|
||||
[attributedString addAttribute:NSForegroundColorAttributeName value:firstWordColor range:firstWordRange];
|
||||
}
|
||||
}
|
||||
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
@end
|
||||
16
examples/ASDKTube/Sample/Models/VideoModel.h
Normal file
16
examples/ASDKTube/Sample/Models/VideoModel.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// VideoModel.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Erekle on 5/14/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface VideoModel : NSObject
|
||||
@property (nonatomic, strong, readonly) NSString* title;
|
||||
@property (nonatomic, strong, readonly) NSURL *url;
|
||||
@property (nonatomic, strong, readonly) NSString *userName;
|
||||
@property (nonatomic, strong, readonly) NSURL *avatarUrl;
|
||||
@end
|
||||
27
examples/ASDKTube/Sample/Models/VideoModel.m
Normal file
27
examples/ASDKTube/Sample/Models/VideoModel.m
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// VideoModel.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Erekle on 5/14/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "VideoModel.h"
|
||||
|
||||
@implementation VideoModel
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSString *videoUrlString = @"https://files.parsetfss.com/8a8a3b0c-619e-4e4d-b1d5-1b5ba9bf2b42/tfss-3045b261-7e93-4492-b7e5-5d6358376c9f-editedLiveAndDie.mov";
|
||||
NSString *avatarUrlString = [NSString stringWithFormat:@"https://api.adorable.io/avatars/50/%@",[[NSProcessInfo processInfo] globallyUniqueString]];
|
||||
|
||||
_title = @"Demo title";
|
||||
_url = [NSURL URLWithString:videoUrlString];
|
||||
_userName = @"Random User";
|
||||
_avatarUrl = [NSURL URLWithString:avatarUrlString];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
14
examples/ASDKTube/Sample/Nodes/VideoContentCell.h
Normal file
14
examples/ASDKTube/Sample/Nodes/VideoContentCell.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// VideoContentCell.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Erekle on 5/14/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
#import "VideoModel.h"
|
||||
|
||||
@interface VideoContentCell : ASCellNode
|
||||
- (instancetype)initWithVideoObject:(VideoModel *)video;
|
||||
@end
|
||||
151
examples/ASDKTube/Sample/Nodes/VideoContentCell.m
Normal file
151
examples/ASDKTube/Sample/Nodes/VideoContentCell.m
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// VideoContentCell.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Erekle on 5/14/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "VideoContentCell.h"
|
||||
#import "ASVideoPlayerNode.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
#define AVATAR_IMAGE_HEIGHT 30
|
||||
#define HORIZONTAL_BUFFER 10
|
||||
#define VERTICAL_BUFFER 5
|
||||
|
||||
@interface VideoContentCell () <ASVideoPlayerNodeDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@implementation VideoContentCell
|
||||
{
|
||||
VideoModel *_videoModel;
|
||||
ASTextNode *_titleNode;
|
||||
ASNetworkImageNode *_avatarNode;
|
||||
ASVideoPlayerNode *_videoPlayerNode;
|
||||
ASControlNode *_likeButtonNode;
|
||||
}
|
||||
|
||||
- (instancetype)initWithVideoObject:(VideoModel *)video
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
_videoModel = video;
|
||||
|
||||
_titleNode = [[ASTextNode alloc] init];
|
||||
_titleNode.attributedText = [[NSAttributedString alloc] initWithString:_videoModel.title attributes:[self titleNodeStringOptions]];
|
||||
_titleNode.flexGrow = YES;
|
||||
[self addSubnode:_titleNode];
|
||||
|
||||
_avatarNode = [[ASNetworkImageNode alloc] init];
|
||||
_avatarNode.URL = _videoModel.avatarUrl;
|
||||
|
||||
[_avatarNode setImageModificationBlock:^UIImage *(UIImage *image) {
|
||||
CGSize profileImageSize = CGSizeMake(AVATAR_IMAGE_HEIGHT, AVATAR_IMAGE_HEIGHT);
|
||||
return [image makeCircularImageWithSize:profileImageSize];
|
||||
}];
|
||||
|
||||
[self addSubnode:_avatarNode];
|
||||
|
||||
_likeButtonNode = [[ASControlNode alloc] init];
|
||||
_likeButtonNode.backgroundColor = [UIColor redColor];
|
||||
[self addSubnode:_likeButtonNode];
|
||||
|
||||
_videoPlayerNode = [[ASVideoPlayerNode alloc] initWithUrl:_videoModel.url];
|
||||
_videoPlayerNode.delegate = self;
|
||||
[self addSubnode:_videoPlayerNode];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSDictionary*)titleNodeStringOptions
|
||||
{
|
||||
return @{
|
||||
NSFontAttributeName : [UIFont systemFontOfSize:14.0],
|
||||
NSForegroundColorAttributeName: [UIColor blackColor]
|
||||
};
|
||||
}
|
||||
|
||||
- (ASLayoutSpec*)layoutSpecThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
CGFloat fullWidth = [UIScreen mainScreen].bounds.size.width;
|
||||
_videoPlayerNode.preferredFrameSize = CGSizeMake(fullWidth, fullWidth * 9 / 16);
|
||||
_avatarNode.preferredFrameSize = CGSizeMake(AVATAR_IMAGE_HEIGHT, AVATAR_IMAGE_HEIGHT);
|
||||
_likeButtonNode.preferredFrameSize = CGSizeMake(50.0, 26.0);
|
||||
|
||||
ASStackLayoutSpec *headerStack = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
headerStack.spacing = HORIZONTAL_BUFFER;
|
||||
headerStack.alignItems = ASStackLayoutAlignItemsCenter;
|
||||
[headerStack setChildren:@[ _avatarNode, _titleNode]];
|
||||
|
||||
UIEdgeInsets headerInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER);
|
||||
ASInsetLayoutSpec *headerInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:headerInsets child:headerStack];
|
||||
|
||||
ASStackLayoutSpec *bottomControlsStack = [ASStackLayoutSpec horizontalStackLayoutSpec];
|
||||
bottomControlsStack.spacing = HORIZONTAL_BUFFER;
|
||||
bottomControlsStack.alignItems = ASStackLayoutAlignItemsCenter;
|
||||
[bottomControlsStack setChildren:@[ _likeButtonNode]];
|
||||
|
||||
UIEdgeInsets bottomControlsInsets = UIEdgeInsetsMake(HORIZONTAL_BUFFER, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER, HORIZONTAL_BUFFER);
|
||||
ASInsetLayoutSpec *bottomControlsInset = [ASInsetLayoutSpec insetLayoutSpecWithInsets:bottomControlsInsets child:bottomControlsStack];
|
||||
|
||||
|
||||
ASStackLayoutSpec *verticalStack = [ASStackLayoutSpec verticalStackLayoutSpec];
|
||||
verticalStack.alignItems = ASStackLayoutAlignItemsStretch;
|
||||
[verticalStack setChildren:@[ headerInset, _videoPlayerNode, bottomControlsInset ]];
|
||||
return verticalStack;
|
||||
}
|
||||
|
||||
#pragma mark - ASVideoPlayerNodeDelegate
|
||||
- (void)videoPlayerNodeWasTapped:(ASVideoPlayerNode *)videoPlayer
|
||||
{
|
||||
if (_videoPlayerNode.playerState == ASVideoNodePlayerStatePlaying) {
|
||||
NSLog(@"TRANSITION");
|
||||
} else {
|
||||
[_videoPlayerNode play];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)videoPlayerNodeNeededControls:(ASVideoPlayerNode *)videoPlayer
|
||||
{
|
||||
return @[ @(ASVideoPlayerNodeControlTypePlaybackButton) ];
|
||||
}
|
||||
|
||||
- (ASLayoutSpec *)videoPlayerNodeLayoutSpec:(ASVideoPlayerNode *)videoPlayer forControls:(NSDictionary *)controls forMaximumSize:(CGSize)maxSize
|
||||
{
|
||||
NSMutableArray *bottomControls = [[NSMutableArray alloc] init];
|
||||
|
||||
ASDisplayNode *playbackButtonNode = controls[@(ASVideoPlayerNodeControlTypePlaybackButton)];
|
||||
|
||||
if (playbackButtonNode) {
|
||||
[bottomControls addObject:playbackButtonNode];
|
||||
}
|
||||
|
||||
ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init];
|
||||
spacer.flexGrow = YES;
|
||||
|
||||
ASStackLayoutSpec *controlbarSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal
|
||||
spacing:10.0
|
||||
justifyContent:ASStackLayoutJustifyContentStart
|
||||
alignItems:ASStackLayoutAlignItemsCenter
|
||||
children:bottomControls];
|
||||
controlbarSpec.alignSelf = ASStackLayoutAlignSelfStretch;
|
||||
|
||||
UIEdgeInsets insets = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
|
||||
|
||||
ASInsetLayoutSpec *controlbarInsetSpec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:insets child:controlbarSpec];
|
||||
|
||||
controlbarInsetSpec.alignSelf = ASStackLayoutAlignSelfStretch;
|
||||
|
||||
ASStackLayoutSpec *mainVerticalStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical
|
||||
spacing:0.0
|
||||
justifyContent:ASStackLayoutJustifyContentStart
|
||||
alignItems:ASStackLayoutAlignItemsStart
|
||||
children:@[ spacer, controlbarInsetSpec ]];
|
||||
|
||||
|
||||
return mainVerticalStack;
|
||||
}
|
||||
@end
|
||||
@@ -8,8 +8,8 @@
|
||||
* 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 <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
#import <AsyncDisplayKit/ASVideoPlayerNode.h>
|
||||
|
||||
@interface ViewController : ASViewController
|
||||
|
||||
|
||||
@@ -10,31 +10,73 @@
|
||||
*/
|
||||
|
||||
#import "ViewController.h"
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
#import <AsyncDisplayKit/ASVideoPlayerNode.h>
|
||||
#import "VideoModel.h"
|
||||
#import "VideoContentCell.h"
|
||||
|
||||
@interface ViewController()<ASVideoPlayerNodeDelegate>
|
||||
@interface ViewController()<ASVideoPlayerNodeDelegate, ASTableDelegate, ASTableDataSource>
|
||||
@property (nonatomic, strong) ASVideoPlayerNode *videoPlayerNode;
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
{
|
||||
ASTableNode *_tableNode;
|
||||
NSMutableArray<VideoModel*> *_videoFeedData;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super initWithNode:self.videoPlayerNode])) {
|
||||
_tableNode = [[ASTableNode alloc] init];
|
||||
_tableNode.delegate = self;
|
||||
_tableNode.dataSource = self;
|
||||
|
||||
if (!(self = [super initWithNode:_tableNode])) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)loadView
|
||||
{
|
||||
[super loadView];
|
||||
|
||||
_videoFeedData = [[NSMutableArray alloc] initWithObjects:[[VideoModel alloc] init], [[VideoModel alloc] init], nil];
|
||||
|
||||
[_tableNode.view reloadData];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
|
||||
//[self.view addSubnode:self.videoPlayerNode];
|
||||
|
||||
//[self.videoPlayerNode setNeedsLayout];
|
||||
}
|
||||
|
||||
#pragma mark - ASCollectionDelegate - ASCollectionDataSource
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
|
||||
return _videoFeedData.count;
|
||||
}
|
||||
|
||||
- (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
VideoModel *videoObject = [_videoFeedData objectAtIndex:indexPath.row];
|
||||
VideoContentCell *cellNode = [[VideoContentCell alloc] initWithVideoObject:videoObject];
|
||||
return cellNode;
|
||||
}
|
||||
|
||||
//- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath{
|
||||
// CGFloat fullWidth = [UIScreen mainScreen].bounds.size.width;
|
||||
// return ASSizeRangeMake(CGSizeMake(fullWidth, 0.0), CGSizeMake(fullWidth, 400.0));
|
||||
//}
|
||||
|
||||
- (ASVideoPlayerNode *)videoPlayerNode;
|
||||
{
|
||||
if (_videoPlayerNode) {
|
||||
@@ -57,47 +99,47 @@
|
||||
}
|
||||
|
||||
#pragma mark - ASVideoPlayerNodeDelegate
|
||||
- (NSArray *)videoPlayerNodeNeededControls:(ASVideoPlayerNode *)videoPlayer
|
||||
{
|
||||
return @[ @(ASVideoPlayerNodeControlTypePlaybackButton),
|
||||
@(ASVideoPlayerNodeControlTypeElapsedText),
|
||||
@(ASVideoPlayerNodeControlTypeScrubber),
|
||||
@(ASVideoPlayerNodeControlTypeDurationText) ];
|
||||
}
|
||||
|
||||
- (UIColor *)videoPlayerNodeScrubberMaximumTrackTint:(ASVideoPlayerNode *)videoPlayer
|
||||
{
|
||||
return [UIColor colorWithRed:1 green:1 blue:1 alpha:0.3];
|
||||
}
|
||||
|
||||
- (UIColor *)videoPlayerNodeScrubberMinimumTrackTint:(ASVideoPlayerNode *)videoPlayer
|
||||
{
|
||||
return [UIColor whiteColor];
|
||||
}
|
||||
|
||||
- (UIColor *)videoPlayerNodeScrubberThumbTint:(ASVideoPlayerNode *)videoPlayer
|
||||
{
|
||||
return [UIColor whiteColor];
|
||||
}
|
||||
|
||||
- (NSDictionary *)videoPlayerNodeTimeLabelAttributes:(ASVideoPlayerNode *)videoPlayerNode timeLabelType:(ASVideoPlayerNodeControlType)timeLabelType
|
||||
{
|
||||
NSDictionary *options;
|
||||
|
||||
if (timeLabelType == ASVideoPlayerNodeControlTypeElapsedText) {
|
||||
options = @{
|
||||
NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:16.0],
|
||||
NSForegroundColorAttributeName: [UIColor orangeColor]
|
||||
};
|
||||
} else if (timeLabelType == ASVideoPlayerNodeControlTypeDurationText) {
|
||||
options = @{
|
||||
NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:16.0],
|
||||
NSForegroundColorAttributeName: [UIColor redColor]
|
||||
};
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
//- (NSArray *)videoPlayerNodeNeededControls:(ASVideoPlayerNode *)videoPlayer
|
||||
//{
|
||||
// return @[ @(ASVideoPlayerNodeControlTypePlaybackButton),
|
||||
// @(ASVideoPlayerNodeControlTypeElapsedText),
|
||||
// @(ASVideoPlayerNodeControlTypeScrubber),
|
||||
// @(ASVideoPlayerNodeControlTypeDurationText) ];
|
||||
//}
|
||||
//
|
||||
//- (UIColor *)videoPlayerNodeScrubberMaximumTrackTint:(ASVideoPlayerNode *)videoPlayer
|
||||
//{
|
||||
// return [UIColor colorWithRed:1 green:1 blue:1 alpha:0.3];
|
||||
//}
|
||||
//
|
||||
//- (UIColor *)videoPlayerNodeScrubberMinimumTrackTint:(ASVideoPlayerNode *)videoPlayer
|
||||
//{
|
||||
// return [UIColor whiteColor];
|
||||
//}
|
||||
//
|
||||
//- (UIColor *)videoPlayerNodeScrubberThumbTint:(ASVideoPlayerNode *)videoPlayer
|
||||
//{
|
||||
// return [UIColor whiteColor];
|
||||
//}
|
||||
//
|
||||
//- (NSDictionary *)videoPlayerNodeTimeLabelAttributes:(ASVideoPlayerNode *)videoPlayerNode timeLabelType:(ASVideoPlayerNodeControlType)timeLabelType
|
||||
//{
|
||||
// NSDictionary *options;
|
||||
//
|
||||
// if (timeLabelType == ASVideoPlayerNodeControlTypeElapsedText) {
|
||||
// options = @{
|
||||
// NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:16.0],
|
||||
// NSForegroundColorAttributeName: [UIColor orangeColor]
|
||||
// };
|
||||
// } else if (timeLabelType == ASVideoPlayerNodeControlTypeDurationText) {
|
||||
// options = @{
|
||||
// NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:16.0],
|
||||
// NSForegroundColorAttributeName: [UIColor redColor]
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// return options;
|
||||
//}
|
||||
|
||||
/*- (ASLayoutSpec *)videoPlayerNodeLayoutSpec:(ASVideoPlayerNode *)videoPlayer
|
||||
forControls:(NSDictionary *)controls
|
||||
|
||||
13
examples/ASDKTube/Sample/WindowWithStatusBarUnderlay.h
Normal file
13
examples/ASDKTube/Sample/WindowWithStatusBarUnderlay.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// WindowWithStatusBarUnderlay.h
|
||||
// Sample
|
||||
//
|
||||
// Created by Hannah Troisi on 4/10/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface WindowWithStatusBarUnderlay : UIWindow
|
||||
|
||||
@end
|
||||
39
examples/ASDKTube/Sample/WindowWithStatusBarUnderlay.m
Normal file
39
examples/ASDKTube/Sample/WindowWithStatusBarUnderlay.m
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// WindowWithStatusBarUnderlay.m
|
||||
// Sample
|
||||
//
|
||||
// Created by Erekle on 5/15/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "WindowWithStatusBarUnderlay.h"
|
||||
#import "Utilities.h"
|
||||
|
||||
@implementation WindowWithStatusBarUnderlay
|
||||
{
|
||||
UIView *_statusBarOpaqueUnderlayView;
|
||||
}
|
||||
|
||||
-(instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
_statusBarOpaqueUnderlayView = [[UIView alloc] init];
|
||||
_statusBarOpaqueUnderlayView.backgroundColor = [UIColor lighOrangeColor];
|
||||
[self addSubview:_statusBarOpaqueUnderlayView];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
[self bringSubviewToFront:_statusBarOpaqueUnderlayView];
|
||||
|
||||
CGRect statusBarFrame = CGRectZero;
|
||||
statusBarFrame.size.width = [[UIScreen mainScreen] bounds].size.width;
|
||||
statusBarFrame.size.height = [[UIApplication sharedApplication] statusBarFrame].size.height;
|
||||
_statusBarOpaqueUnderlayView.frame = statusBarFrame;
|
||||
}
|
||||
@end
|
||||
@@ -254,12 +254,12 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 05E212A419D4DB510098F589 /* Build configuration list for PBXNativeTarget "Sample" */;
|
||||
buildPhases = (
|
||||
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */,
|
||||
E080B80F89C34A25B3488E26 /* 📦 Check Pods Manifest.lock */,
|
||||
05E2127D19D4DB510098F589 /* Sources */,
|
||||
05E2127E19D4DB510098F589 /* Frameworks */,
|
||||
05E2127F19D4DB510098F589 /* Resources */,
|
||||
F012A6F39E0149F18F564F50 /* Copy Pods Resources */,
|
||||
06770D39D4186D6446B1BDD5 /* Embed Pods Frameworks */,
|
||||
F012A6F39E0149F18F564F50 /* 📦 Copy Pods Resources */,
|
||||
06770D39D4186D6446B1BDD5 /* 📦 Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -319,14 +319,14 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
06770D39D4186D6446B1BDD5 /* Embed Pods Frameworks */ = {
|
||||
06770D39D4186D6446B1BDD5 /* 📦 Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Embed Pods Frameworks";
|
||||
name = "📦 Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -334,14 +334,14 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sample/Pods-Sample-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E080B80F89C34A25B3488E26 /* Check Pods Manifest.lock */ = {
|
||||
E080B80F89C34A25B3488E26 /* 📦 Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Check Pods Manifest.lock";
|
||||
name = "📦 Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -349,14 +349,14 @@
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F012A6F39E0149F18F564F50 /* Copy Pods Resources */ = {
|
||||
F012A6F39E0149F18F564F50 /* 📦 Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
name = "📦 Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
10
examples/ASDKgram/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
examples/ASDKgram/Sample.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Sample.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
Reference in New Issue
Block a user