From e7cf8782b4b0b0cac805430543e6ef9f5cffcbd5 Mon Sep 17 00:00:00 2001 From: Ash Mishra Date: Wed, 24 Apr 2019 12:05:16 -0700 Subject: [PATCH 1/2] Fix for fullscreen presentation of video by method calls --- examples/embed-and-fullscreen/index.ios.js | 1 + ios/RCTVideo.xcodeproj/project.pbxproj | 7 +++ ios/Video/AVPlayerViewController+Fullscreen.h | 20 +++++++++ ios/Video/AVPlayerViewController+Fullscreen.m | 43 +++++++++++++++++++ ios/Video/RCTVideo.m | 11 ++--- ios/Video/RCTVideoPlayerViewController.h | 1 + 6 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 ios/Video/AVPlayerViewController+Fullscreen.h create mode 100644 ios/Video/AVPlayerViewController+Fullscreen.m diff --git a/examples/embed-and-fullscreen/index.ios.js b/examples/embed-and-fullscreen/index.ios.js index ba2f1ceb54..8c5e7aa3a3 100644 --- a/examples/embed-and-fullscreen/index.ios.js +++ b/examples/embed-and-fullscreen/index.ios.js @@ -36,6 +36,7 @@ export default class VideoPlayer extends Component { source={require('./broadchurch.mp4')} style={{width: this.state.orientationWidth, height: this.state.orientationHeight }} controls={true} + onLoad={() => this.videoPlayer && this.videoPlayer.presentFullscreenPlayer()} /> diff --git a/ios/RCTVideo.xcodeproj/project.pbxproj b/ios/RCTVideo.xcodeproj/project.pbxproj index 4e675ac782..3572c03664 100644 --- a/ios/RCTVideo.xcodeproj/project.pbxproj +++ b/ios/RCTVideo.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ D1107C0F2110259000073188 /* RCTVideoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D1107C062110259000073188 /* RCTVideoManager.m */; }; D1107C102110259000073188 /* RCTVideoPlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D1107C082110259000073188 /* RCTVideoPlayerViewController.m */; }; D1107C112110259000073188 /* RCTVideoPlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D1107C082110259000073188 /* RCTVideoPlayerViewController.m */; }; + FA5A7A5B2270E5870086953B /* AVPlayerViewController+Fullscreen.m in Sources */ = {isa = PBXBuildFile; fileRef = FA5A7A5A2270E5870086953B /* AVPlayerViewController+Fullscreen.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -50,6 +51,8 @@ D1107C072110259000073188 /* RCTVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTVideo.h; path = Video/RCTVideo.h; sourceTree = ""; }; D1107C082110259000073188 /* RCTVideoPlayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTVideoPlayerViewController.m; path = Video/RCTVideoPlayerViewController.m; sourceTree = ""; }; D1107C092110259000073188 /* RCTVideoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTVideoManager.h; path = Video/RCTVideoManager.h; sourceTree = ""; }; + FA5A7A592270E5870086953B /* AVPlayerViewController+Fullscreen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "AVPlayerViewController+Fullscreen.h"; path = "Video/AVPlayerViewController+Fullscreen.h"; sourceTree = ""; }; + FA5A7A5A2270E5870086953B /* AVPlayerViewController+Fullscreen.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "AVPlayerViewController+Fullscreen.m"; path = "Video/AVPlayerViewController+Fullscreen.m"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -88,6 +91,8 @@ 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( + FA5A7A592270E5870086953B /* AVPlayerViewController+Fullscreen.h */, + FA5A7A5A2270E5870086953B /* AVPlayerViewController+Fullscreen.m */, D1107C072110259000073188 /* RCTVideo.h */, D1107C052110259000073188 /* RCTVideo.m */, D1107C092110259000073188 /* RCTVideoManager.h */, @@ -163,6 +168,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 58B511D21A9E6C8500147676; @@ -184,6 +190,7 @@ D1107C0A2110259000073188 /* UIView+FindUIViewController.m in Sources */, D1107C102110259000073188 /* RCTVideoPlayerViewController.m in Sources */, D1107C0E2110259000073188 /* RCTVideoManager.m in Sources */, + FA5A7A5B2270E5870086953B /* AVPlayerViewController+Fullscreen.m in Sources */, D1107C0C2110259000073188 /* RCTVideo.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/Video/AVPlayerViewController+Fullscreen.h b/ios/Video/AVPlayerViewController+Fullscreen.h new file mode 100644 index 0000000000..599d7287de --- /dev/null +++ b/ios/Video/AVPlayerViewController+Fullscreen.h @@ -0,0 +1,20 @@ +// +// NSObject+AVPlayerViewController_Fullscreen.h +// RCTVideo +// +// Created by Ash on 2019-04-24. +// Copyright © 2019 Facebook. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AVPlayerViewController (Fullscreen) + +-(void)goFullscreen; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/Video/AVPlayerViewController+Fullscreen.m b/ios/Video/AVPlayerViewController+Fullscreen.m new file mode 100644 index 0000000000..9078c76e0b --- /dev/null +++ b/ios/Video/AVPlayerViewController+Fullscreen.m @@ -0,0 +1,43 @@ +// +// NSObject+AVPlayerViewController_Fullscreen.m +// RCTVideo +// +// Created by Ash on 2019-04-24. +// Copyright © 2019 Facebook. All rights reserved. +// + +#import "AVPlayerViewController+Fullscreen.h" + +@implementation AVPlayerViewController (Fullscreen) + +-(void)goFullscreen { + NSString *selectorForFullscreen = @"transitionToFullScreenViewControllerAnimated:completionHandler:"; + if (@available(iOS 11.3, *)) { + selectorForFullscreen = @"transitionToFullScreenAnimated:interactive:completionHandler:"; + } else if (@available(iOS 11.0, *)) { + selectorForFullscreen = @"transitionToFullScreenAnimated:completionHandler:"; + } + SEL fsSelector = NSSelectorFromString([@"_" stringByAppendingString:selectorForFullscreen]); + if ([self respondsToSelector:fsSelector]) { + NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:fsSelector]]; + [inv setSelector:fsSelector]; + [inv setTarget:self]; + + NSInteger index = 2; //arguments 0 and 1 are self and _cmd respectively, automatically set + BOOL animated = YES; + [inv setArgument:&(animated) atIndex:index]; + index++; + + if (@available(iOS 11.3, *)) { + BOOL interactive = YES; + [inv setArgument:&(interactive) atIndex:index]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation + index++; + } + + id completionBlock = nil; + [inv setArgument:&(completionBlock) atIndex:index]; + [inv invoke]; + } +} + +@end diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index dcadee85f4..982571fad8 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1246,14 +1246,9 @@ - (void)setFullscreen:(BOOL) fullscreen { if(self.onVideoFullscreenPlayerWillPresent) { self.onVideoFullscreenPlayerWillPresent(@{@"target": self.reactTag}); } - [viewController presentViewController:_playerViewController animated:true completion:^{ - _playerViewController.showsPlaybackControls = YES; - _fullscreenPlayerPresented = fullscreen; - _playerViewController.autorotate = _fullscreenAutorotate; - if(self.onVideoFullscreenPlayerDidPresent) { - self.onVideoFullscreenPlayerDidPresent(@{@"target": self.reactTag}); - } - }]; + [_playerViewController removeFromParentViewController]; + + [_playerViewController goFullscreen]; } } else if ( !fullscreen && _fullscreenPlayerPresented ) diff --git a/ios/Video/RCTVideoPlayerViewController.h b/ios/Video/RCTVideoPlayerViewController.h index ed9ebdde09..9be17f79b0 100644 --- a/ios/Video/RCTVideoPlayerViewController.h +++ b/ios/Video/RCTVideoPlayerViewController.h @@ -9,6 +9,7 @@ #import #import "RCTVideo.h" #import "RCTVideoPlayerViewControllerDelegate.h" +#import "AVPlayerViewController+Fullscreen.h" @interface RCTVideoPlayerViewController : AVPlayerViewController @property (nonatomic, weak) id rctDelegate; From a17b183f105cbd24743447db8598b916b6da842b Mon Sep 17 00:00:00 2001 From: Ash Mishra Date: Wed, 1 May 2019 12:48:11 -0700 Subject: [PATCH 2/2] further fixes Fix for fullscreen presentation of video by method calls --- examples/embed-and-fullscreen/index.ios.js | 25 ++++++++++- .../ios/VideoPlayer.xcodeproj/project.pbxproj | 3 ++ ios/Video/AVPlayerViewController+Fullscreen.h | 2 +- ios/Video/AVPlayerViewController+Fullscreen.m | 3 +- ios/Video/RCTVideo.m | 45 +++++++++++++++++-- 5 files changed, 70 insertions(+), 8 deletions(-) diff --git a/examples/embed-and-fullscreen/index.ios.js b/examples/embed-and-fullscreen/index.ios.js index 8c5e7aa3a3..14113473aa 100644 --- a/examples/embed-and-fullscreen/index.ios.js +++ b/examples/embed-and-fullscreen/index.ios.js @@ -36,12 +36,35 @@ export default class VideoPlayer extends Component { source={require('./broadchurch.mp4')} style={{width: this.state.orientationWidth, height: this.state.orientationHeight }} controls={true} - onLoad={() => this.videoPlayer && this.videoPlayer.presentFullscreenPlayer()} + onLoad={() => { console.log('log: onload'); } } + + onFullscreenPlayerWillPresent={ this.videoPlayerWillPresent } + onFullscreenPlayerDidPresent={ this.videoPlayerDidPresent } + onFullscreenPlayerWillDismiss={ this.videoPlayerWillDismiss } + onFullscreenPlayerDidDismiss={ this.videoPlayerDidDismiss } + + onEnd={() => { console.log('log: onEnd'); }} /> } + videoPlayerWillPresent() { + console.log('log: will present'); + } + + videoPlayerDidPresent() { + console.log('log: did present'); + } + + videoPlayerWillDismiss() { + console.log('log: will dismiss'); + } + + videoPlayerDidDismiss() { + console.log('log: did dismiss'); + } + onPress() { if (this.videoPlayer!=null) this.videoPlayer.presentFullscreenPlayer(); diff --git a/examples/embed-and-fullscreen/ios/VideoPlayer.xcodeproj/project.pbxproj b/examples/embed-and-fullscreen/ios/VideoPlayer.xcodeproj/project.pbxproj index 0d077be9df..2927e729be 100644 --- a/examples/embed-and-fullscreen/ios/VideoPlayer.xcodeproj/project.pbxproj +++ b/examples/embed-and-fullscreen/ios/VideoPlayer.xcodeproj/project.pbxproj @@ -609,6 +609,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -1028,6 +1029,7 @@ DEAD_CODE_STRIPPING = NO; HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = VideoPlayer/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", @@ -1047,6 +1049,7 @@ CURRENT_PROJECT_VERSION = 1; HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = VideoPlayer/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", diff --git a/ios/Video/AVPlayerViewController+Fullscreen.h b/ios/Video/AVPlayerViewController+Fullscreen.h index 599d7287de..892ad4e8cd 100644 --- a/ios/Video/AVPlayerViewController+Fullscreen.h +++ b/ios/Video/AVPlayerViewController+Fullscreen.h @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN @interface AVPlayerViewController (Fullscreen) --(void)goFullscreen; +-(void)goFullscreenWithCompletionHandler:(void (^)(void)) completionBlock; @end diff --git a/ios/Video/AVPlayerViewController+Fullscreen.m b/ios/Video/AVPlayerViewController+Fullscreen.m index 9078c76e0b..c9316dd072 100644 --- a/ios/Video/AVPlayerViewController+Fullscreen.m +++ b/ios/Video/AVPlayerViewController+Fullscreen.m @@ -10,7 +10,7 @@ @implementation AVPlayerViewController (Fullscreen) --(void)goFullscreen { +-(void)goFullscreenWithCompletionHandler:(void (^)(void)) completionBlock { NSString *selectorForFullscreen = @"transitionToFullScreenViewControllerAnimated:completionHandler:"; if (@available(iOS 11.3, *)) { selectorForFullscreen = @"transitionToFullScreenAnimated:interactive:completionHandler:"; @@ -34,7 +34,6 @@ -(void)goFullscreen { index++; } - id completionBlock = nil; [inv setArgument:&(completionBlock) atIndex:index]; [inv invoke]; } diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 982571fad8..81a25cab57 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -587,8 +587,29 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N if (!CGRectEqualToRect(oldRect, newRect)) { if (CGRectEqualToRect(newRect, [UIScreen mainScreen].bounds)) { - NSLog(@"in fullscreen"); - } else NSLog(@"not fullscreen"); + NSLog(@"log: in fullscreen"); + + if (!_fullscreenPlayerPresented) { + if(self.onVideoFullscreenPlayerDidPresent) { + self.onVideoFullscreenPlayerDidPresent(@{@"target": self.reactTag}); + } + } + _fullscreenPlayerPresented = true; + } else { + NSLog(@"log: not fullscreen"); + + if (_fullscreenPlayerPresented) { + if(self.onVideoFullscreenPlayerDidDismiss) { + self.onVideoFullscreenPlayerWillDismiss(@{@"target": self.reactTag}); + } + if(self.onVideoFullscreenPlayerDidDismiss) { + self.onVideoFullscreenPlayerDidDismiss(@{@"target": self.reactTag}); + } + } + + _fullscreenPlayerPresented = false; + + } [self.reactViewController.view setFrame:[UIScreen mainScreen].bounds]; [self.reactViewController.view setNeedsLayout]; @@ -1246,9 +1267,25 @@ - (void)setFullscreen:(BOOL) fullscreen { if(self.onVideoFullscreenPlayerWillPresent) { self.onVideoFullscreenPlayerWillPresent(@{@"target": self.reactTag}); } - [_playerViewController removeFromParentViewController]; - [_playerViewController goFullscreen]; + if (_controls) { + + [_playerViewController removeFromParentViewController]; + [_playerViewController goFullscreenWithCompletionHandler:^{ + + _playerViewController.showsPlaybackControls = YES; + _playerViewController.autorotate = _fullscreenAutorotate; + }]; + } else { + [viewController presentViewController:_playerViewController animated:true completion:^{ + _playerViewController.showsPlaybackControls = YES; + _fullscreenPlayerPresented = fullscreen; + _playerViewController.autorotate = _fullscreenAutorotate; + if(self.onVideoFullscreenPlayerDidPresent) { + self.onVideoFullscreenPlayerDidPresent(@{@"target": self.reactTag}); + } + }]; + } } } else if ( !fullscreen && _fullscreenPlayerPresented )