diff --git a/AsyncDisplayKit/ASVideoNode.h b/AsyncDisplayKit/ASVideoNode.h index e998c04bdf..a4ce9cdaf0 100644 --- a/AsyncDisplayKit/ASVideoNode.h +++ b/AsyncDisplayKit/ASVideoNode.h @@ -58,9 +58,6 @@ NS_ASSUME_NONNULL_BEGIN //! Defaults to AVLayerVideoGravityResizeAspect @property (atomic) NSString *gravity; -//! Defaults to an ASDefaultPlayButton instance. -@property (nullable, atomic) ASButtonNode *playButton; - @property (nullable, atomic, weak, readwrite) id delegate; @end diff --git a/AsyncDisplayKit/ASVideoNode.mm b/AsyncDisplayKit/ASVideoNode.mm index e58ced6ca4..8c305559cc 100644 --- a/AsyncDisplayKit/ASVideoNode.mm +++ b/AsyncDisplayKit/ASVideoNode.mm @@ -63,8 +63,7 @@ static NSString * const kStatus = @"status"; CMTime _timeObserverInterval; ASImageNode *_placeholderImageNode; // TODO: Make ASVideoNode an ASImageNode subclass; remove this. - - ASButtonNode *_playButtonNode; + ASDisplayNode *_playerNode; ASDisplayNode *_spinnerNode; NSString *_gravity; @@ -83,8 +82,7 @@ static NSString * const kStatus = @"status"; if (!(self = [super init])) { return nil; } - - self.playButton = [[ASDefaultPlayButton alloc] init]; + self.gravity = AVLayerVideoGravityResizeAspect; _periodicTimeObserverTimescale = 10000; [self addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside]; @@ -201,10 +199,7 @@ static NSString * const kStatus = @"status"; // Stretch out play button, placeholder image player node to the max size NSMutableArray *children = [NSMutableArray array]; - if (_playButtonNode) { - _playButtonNode.preferredFrameSize = maxSize; - [children addObject:_playButtonNode]; - } + if (_placeholderImageNode) { _placeholderImageNode.preferredFrameSize = maxSize; [children addObject:_placeholderImageNode]; @@ -224,18 +219,6 @@ static NSString * const kStatus = @"status"; return [ASStaticLayoutSpec staticLayoutSpecWithChildren:children]; } -- (void)layout -{ - [super layout]; - - CGRect bounds = self.bounds; - - ASDN::MutexLocker l(_videoLock); - CGFloat horizontalDiff = (CGRectGetWidth(bounds) - CGRectGetWidth(_playButtonNode.bounds))/2; - CGFloat verticalDiff = (CGRectGetHeight(bounds) - CGRectGetHeight(_playButtonNode.bounds))/2; - _playButtonNode.hitTestSlop = UIEdgeInsetsMake(-verticalDiff, -horizontalDiff, -verticalDiff, -horizontalDiff); -} - - (void)generatePlaceholderImage { ASVideoNode * __weak weakSelf = self; @@ -421,26 +404,6 @@ static NSString * const kStatus = @"status"; _playerState = playerState; } -- (void)setPlayButton:(ASButtonNode *)playButton -{ - ASDN::MutexLocker l(_videoLock); - - [_playButtonNode removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside]; - [_playButtonNode removeFromSupernode]; - - _playButtonNode = playButton; - [_playButtonNode addTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside]; - - [self addSubnode:playButton]; - [self setNeedsLayout]; -} - -- (ASButtonNode *)playButton -{ - ASDN::MutexLocker l(_videoLock); - return _playButtonNode; -} - - (void)setAsset:(AVAsset *)asset { ASDN::MutexLocker l(_videoLock); @@ -537,11 +500,8 @@ static NSString * const kStatus = @"status"; if (_playerNode == nil) { _playerNode = [self constructPlayerNode]; - if (_playButtonNode.supernode == self) { - [self insertSubnode:_playerNode belowSubnode:_playButtonNode]; - } else { - [self addSubnode:_playerNode]; - } + [self addSubnode:_playerNode]; + [self setNeedsLayout]; } @@ -549,10 +509,7 @@ static NSString * const kStatus = @"status"; [_player play]; _shouldBePlaying = YES; - - [UIView animateWithDuration:0.15 animations:^{ - _playButtonNode.alpha = 0.0; - }]; + if (![self ready]) { [self showSpinner]; } else { @@ -605,9 +562,6 @@ static NSString * const kStatus = @"status"; [_player pause]; [self removeSpinner]; _shouldBePlaying = NO; - [UIView animateWithDuration:0.15 animations:^{ - _playButtonNode.alpha = 1.0; - }]; } - (BOOL)isPlaying @@ -733,7 +687,6 @@ static NSString * const kStatus = @"status"; { [_player removeTimeObserver:_timeObserver]; _timeObserver = nil; - [_playButtonNode removeTarget:self action:@selector(tapped) forControlEvents:ASControlNodeEventTouchUpInside]; [self removePlayerItemObservers:_currentPlayerItem]; } diff --git a/AsyncDisplayKit/ASVideoPlayerNode.h b/AsyncDisplayKit/ASVideoPlayerNode.h index f3a9502d49..1183a53467 100644 --- a/AsyncDisplayKit/ASVideoPlayerNode.h +++ b/AsyncDisplayKit/ASVideoPlayerNode.h @@ -66,6 +66,9 @@ NS_ASSUME_NONNULL_BEGIN * @param timeLabelType */ - (NSDictionary *)videoPlayerNodeTimeLabelAttributes:(ASVideoPlayerNode *)videoPlayerNode timeLabelType:(ASVideoPlayerNodeControlType)timeLabelType; +- (NSString *)videoPlayerNode:(ASVideoPlayerNode *)videoPlayerNode + timeStringForTimeLabelType:(ASVideoPlayerNodeControlType)timeLabelType + forTime:(CMTime)time; #pragma mark Scrubber delegate methods - (UIColor *)videoPlayerNodeScrubberMaximumTrackTint:(ASVideoPlayerNode *)videoPlayer; diff --git a/AsyncDisplayKit/ASVideoPlayerNode.mm b/AsyncDisplayKit/ASVideoPlayerNode.mm index d01fc6d914..a4d17bde9a 100644 --- a/AsyncDisplayKit/ASVideoPlayerNode.mm +++ b/AsyncDisplayKit/ASVideoPlayerNode.mm @@ -23,6 +23,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; unsigned int delegateScrubberThumbTintColor:1; unsigned int delegateScrubberThumbImage:1; unsigned int delegateTimeLabelAttributes:1; + unsigned int delegateTimeLabelAttributedString:1; unsigned int delegateLayoutSpecForControls:1; unsigned int delegateVideoNodeDidPlayToTime:1; unsigned int delegateVideoNodeWillChangeState:1; @@ -176,12 +177,13 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; - (void)removeControls { -// [_cachedControls enumerateObjectsUsingBlock:^(ASDisplayNode *_Nonnull node, NSUInteger idx, BOOL * _Nonnull stop) { -// [node.view removeFromSuperview]; -// [node removeFromSupernode]; -// node = nil; -// NSLog(@"%@",_playbackButtonNode); -// }]; + NSArray *controls = [_cachedControls allValues]; + [controls enumerateObjectsUsingBlock:^(ASDisplayNode *_Nonnull node, NSUInteger idx, BOOL * _Nonnull stop) { + [node.view removeFromSuperview]; + [node removeFromSupernode]; + //node = nil; + NSLog(@"%@",_playbackButtonNode); + }]; } - (void)createPlaybackButton @@ -272,13 +274,13 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; - (void)updateDurationTimeLabel { - NSString *formatedDuration = [self timeStringForCMTime:_duration]; + NSString *formatedDuration = [self timeStringForCMTime:_duration forTimeLabelType:ASVideoPlayerNodeControlTypeDurationText]; _durationTextNode.attributedString = [self timeLabelAttributedStringForString:formatedDuration forControlType:ASVideoPlayerNodeControlTypeDurationText]; } - (void)updateElapsedTimeLabel:(NSTimeInterval)seconds { - NSString *formatedDuration = [self timeStringForCMTime:CMTimeMakeWithSeconds( seconds, _videoNode.periodicTimeObserverTimescale )]; + NSString *formatedDuration = [self timeStringForCMTime:CMTimeMakeWithSeconds( seconds, _videoNode.periodicTimeObserverTimescale ) forTimeLabelType:ASVideoPlayerNodeControlTypeElapsedText]; _elapsedTextNode.attributedString = [self timeLabelAttributedStringForString:formatedDuration forControlType:ASVideoPlayerNodeControlTypeElapsedText]; } @@ -307,7 +309,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; [_delegate videoPlayerNode:self willChangeVideoNodeState:state toVideoNodeState:toState]; } - if (toState == ASVideoNodePlayerStateReadyToPlay) { + if (toState == ASVideoNodePlayerStateReadyToPlay && _durationTextNode) { _duration = _videoNode.currentItem.duration; [self updateDurationTimeLabel]; } @@ -334,8 +336,13 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; return; } - [self updateElapsedTimeLabel:second]; - [(UISlider*)_scrubberNode.view setValue:(second/ CMTimeGetSeconds(_duration) ) animated:NO]; + if (_elapsedTextNode) { + [self updateElapsedTimeLabel:second]; + } + + if (_scrubberNode) { + [(UISlider*)_scrubberNode.view setValue:(second/ CMTimeGetSeconds(_duration) ) animated:NO]; + } } - (void)videoPlaybackDidFinish:(ASVideoNode *)videoNode @@ -343,7 +350,6 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; if (_delegateFlags.delegateVideoNodePlaybackDidFinish) { [_delegate videoPlayerNodePlaybackDidFinish:self]; } - //[self removeControls]; } #pragma mark - Actions @@ -423,6 +429,7 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; } ASOverlayLayoutSpec *overlaySpec = [ASOverlayLayoutSpec overlayLayoutSpecWithChild:_videoNode overlay:layoutSpec]; + overlaySpec.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(constrainedSize.max); return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[overlaySpec]]; } @@ -479,13 +486,17 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext; _delegateFlags.delegateVideoNodeWillChangeState = [_delegate respondsToSelector:@selector(videoPlayerNode:willChangeVideoNodeState:toVideoNodeState:)]; _delegateFlags.delegateVideoNodePlaybackDidFinish = [_delegate respondsToSelector:@selector(videoPlayerNodePlaybackDidFinish:)]; _delegateFlags.delegateVideoNodeShouldChangeState = [_delegate respondsToSelector:@selector(videoPlayerNode:shouldChangeVideoNodeStateTo:)]; + _delegateFlags.delegateTimeLabelAttributedString = [_delegate respondsToSelector:@selector(videoPlayerNode:timeStringForTimeLabelType:forTime:)]; } } #pragma mark - Helpers -- (NSString *)timeStringForCMTime:(CMTime)time +- (NSString *)timeStringForCMTime:(CMTime)time forTimeLabelType:(ASVideoPlayerNodeControlType)type { - //TODO: ask Max if delegate for this thing will be useful; + if (_delegateFlags.delegateTimeLabelAttributedString) { + return [_delegate videoPlayerNode:self timeStringForTimeLabelType:type forTime:time]; + } + NSUInteger dTotalSeconds = CMTimeGetSeconds(time); NSUInteger dHours = floor(dTotalSeconds / 3600); diff --git a/AsyncDisplayKitTests/ASVideoNodeTests.m b/AsyncDisplayKitTests/ASVideoNodeTests.m index 6530edd4f6..eaa7e63a5b 100644 --- a/AsyncDisplayKitTests/ASVideoNodeTests.m +++ b/AsyncDisplayKitTests/ASVideoNodeTests.m @@ -379,21 +379,6 @@ XCTAssertEqual(UIViewContentModeScaleAspectFill, _videoNode.placeholderImageNode.contentMode); } -- (void)testChangingPlayButtonPerformsProperCleanup -{ - ASButtonNode *firstButton = _videoNode.playButton; - XCTAssertTrue([firstButton.allTargets containsObject:_videoNode]); - - ASButtonNode *secondButton = [[ASButtonNode alloc] init]; - _videoNode.playButton = secondButton; - - XCTAssertTrue([secondButton.allTargets containsObject:_videoNode]); - XCTAssertEqual(_videoNode, secondButton.supernode); - - XCTAssertFalse([firstButton.allTargets containsObject:_videoNode]); - XCTAssertNotEqual(_videoNode, firstButton.supernode); -} - - (void)testChangingAssetsChangesPlaceholderImage { UIImage *firstImage = [[UIImage alloc] init];