Address some of the feedback from the pull reqeust

This commit is contained in:
Abdulrahman Alzenki 2018-11-26 14:23:04 -08:00 committed by Abdulrahman Alzenki
parent 4a16151195
commit 62dc913cb3
5 changed files with 79 additions and 107 deletions

101
README.md
View File

@ -271,6 +271,7 @@ var styles = StyleSheet.create({
* [maxBitRate](#maxbitrate)
* [muted](#muted)
* [paused](#paused)
* [pictureInPicture](#pictureinpicture)
* [playInBackground](#playinbackground)
* [playWhenInactive](#playwheninactive)
* [poster](#poster)
@ -298,12 +299,12 @@ var styles = StyleSheet.create({
* [onFullscreenPlayerDidPresent](#onfullscreenplayerdidpresent)
* [onFullscreenPlayerWillDismiss](#onfullscreenplayerwilldismiss)
* [onFullscreenPlayerDidDismiss](#onfullscreenplayerdiddismiss)
* [onIsPictureInPictureActive](#onispictureinpictureactive)
* [onIsPictureInPictureSupported](#onispictureinpicturesupported)
* [onLoad](#onload)
* [onLoadStart](#onloadstart)
* [onPictureInPictureStatusChanged](#onpictureinpicturestatuschanged)
* [onProgress](#onprogress)
* [onSeek](#onseek)
* [onRestoreUserInterfaceForPictureInPictureStop](#onrestoreuserinterfaceforpictureinpicturestop)
* [onTimedMetadata](#ontimedmetadata)
### Methods
@ -311,9 +312,7 @@ var styles = StyleSheet.create({
* [presentFullscreenPlayer](#presentfullscreenplayer)
* [save](#save)
* [restoreUserInterfaceForPictureInPictureStop](#restoreuserinterfaceforpictureinpicturestop)
* [startPictureInPicture](#startpictureinpicture)
* [seek](#seek)
* [stopPictureInPicture](#stoppictureinpicture)
### Configurable props
@ -491,6 +490,13 @@ Controls whether the media is paused
Platforms: all
#### pictureInPicture
Determine whether the media should played as picture in picture.
* **false (default)** - Don't not play as picture in picture
* **true** - Play the media as picture in picture
Platforms: iOS
#### playInBackground
Determine whether the media should continue playing while the app is in the background. This allows customers to continue listening to the audio.
* **false (default)** - Don't continue playing the media
@ -866,38 +872,6 @@ Payload: none
Platforms: Android ExoPlayer, Android MediaPlayer, iOS
#### onIsPictureInPictureActive
Callback function that is called when picture in picture becomes active or inactive.
Property | Type | Description
--- | --- | ---
active | boolean | Boolean indicating whether picture in picture is active
Example:
```
{
active: true
}
```
Platforms: iOS
#### onIsPictureInPictureSupported
Callback function that is called initially to determine whether or not picture in picture is supported.
Property | Type | Description
--- | --- | ---
supported | boolean | Boolean indicating whether picture in picture is supported
Example:
```
{
supported: true
}
```
Platforms: iOS
#### onLoad
Callback function that is called when the media is loaded and ready to play.
@ -963,6 +937,22 @@ Example:
Platforms: all
#### onPictureInPictureStatusChanged
Callback function that is called when picture in picture becomes active or inactive.
Property | Type | Description
--- | --- | ---
isActive | boolean | Boolean indicating whether picture in picture is active
Example:
```
{
isActive: true
}
```
Platforms: iOS
#### onProgress
Callback function that is called every progressUpdateInterval seconds with info about which position the media is currently playing.
@ -1006,6 +996,13 @@ Both the currentTime & seekTime are reported because the video player may not se
Platforms: Android ExoPlayer, Android MediaPlayer, iOS, Windows UWP
#### onRestoreUserInterfaceForPictureInPictureStop
Callback function that corresponds to Apple's [`restoreUserInterfaceForPictureInPictureStopWithCompletionHandler`](https://developer.apple.com/documentation/avkit/avpictureinpicturecontrollerdelegate/1614703-pictureinpicturecontroller?language=objc). Call `restoreUserInterfaceForPictureInPictureStopCompleted` inside of this function when done restoring the user interface.
Payload: none
Platforms: iOS
#### onTimedMetadata
Callback function that is called when timed metadata becomes available
@ -1094,26 +1091,14 @@ Future:
Platforms: iOS
#### restoreUserInterfaceForPictureInPictureStop
`restoreUserInterfaceForPictureInPictureStop(restore)`
#### restoreUserInterfaceForPictureInPictureStopCompleted
`restoreUserInterfaceForPictureInPictureStopCompleted(restored)`
This function corresponds to Apple's [restoreUserInterfaceForPictureInPictureStop](https://developer.apple.com/documentation/avkit/avpictureinpicturecontrollerdelegate/1614703-pictureinpicturecontroller?language=objc). IMPORTANT: After picture in picture stops, this function must be called.
This function corresponds to the completion handler in Apple's [restoreUserInterfaceForPictureInPictureStop](https://developer.apple.com/documentation/avkit/avpictureinpicturecontrollerdelegate/1614703-pictureinpicturecontroller?language=objc). IMPORTANT: This function must be called after `onRestoreUserInterfaceForPictureInPictureStop` is called.
Example:
```
this.player.restoreUserInterfaceForPictureInPictureStop(true);
```
Platforms: iOS
#### startPictureInPicture
`startPictureInPicture()`
Calling this function will start picture in picture if it is supported.
Example:
```
this.player.startPictureInPicture();
this.player.restoreUserInterfaceForPictureInPictureStopCompleted(true);
```
Platforms: iOS
@ -1147,18 +1132,6 @@ this.player.seek(120, 50); // Seek to 2 minutes with +/- 50 milliseconds accurac
Platforms: iOS
#### stopPictureInPicture
`stopPictureInPicture()`
Calling this function will stop picture in picture if it is currently active.
Example:
```
this.player.stopPictureInPicture();
```
Platforms: iOS

View File

@ -78,16 +78,8 @@ export default class Video extends Component {
return await NativeModules.VideoManager.save(options, findNodeHandle(this._root));
}
startPictureInPicture = () => {
this.setNativeProps({ pictureInPicture: true });
};
stopPictureInPicture = () => {
this.setNativeProps({ pictureInPicture: false });
};
restoreUserInterfaceForPictureInPictureStop = (restore) => {
this.setNativeProps({ restoreUserInterfaceForPIPStopCompletionHandler: restore });
restoreUserInterfaceForPictureInPictureStopCompleted = (restored) => {
this.setNativeProps({ restoreUserInterfaceForPIPStopCompletionHandler: restored });
};
_assignRoot = (component) => {
@ -210,15 +202,15 @@ export default class Video extends Component {
}
};
_onIsPictureInPictureSupported = (event) => {
if (this.props.onIsPictureInPictureSupported) {
this.props.onIsPictureInPictureSupported(event.nativeEvent);
_onPictureInPictureStatusChanged = (event) => {
if (this.props.onPictureInPictureStatusChanged) {
this.props.onPictureInPictureStatusChanged(event.nativeEvent);
}
};
_onIsPictureInPictureActive = (event) => {
if (this.props.onIsPictureInPictureActive) {
this.props.onIsPictureInPictureActive(event.nativeEvent);
_onRestoreUserInterfaceForPictureInPictureStop = (event) => {
if (this.props.onRestoreUserInterfaceForPictureInPictureStop) {
this.props.onRestoreUserInterfaceForPictureInPictureStop();
}
};
@ -291,8 +283,8 @@ export default class Video extends Component {
onPlaybackRateChange: this._onPlaybackRateChange,
onAudioFocusChanged: this._onAudioFocusChanged,
onAudioBecomingNoisy: this._onAudioBecomingNoisy,
onIsPictureInPictureSupported: this._onIsPictureInPictureSupported,
onIsPictureInPictureActive: this._onIsPictureInPictureActive,
onPictureInPictureStatusChanged: this._onPictureInPictureStatusChanged,
onRestoreUserInterfaceForPictureInPictureStop: this._onRestoreUserInterfaceForPictureInPictureStop,
});
const posterStyle = {
@ -415,6 +407,7 @@ Video.propTypes = {
}),
stereoPan: PropTypes.number,
rate: PropTypes.number,
pictureInPicture: PropTypes.bool,
playInBackground: PropTypes.bool,
playWhenInactive: PropTypes.bool,
ignoreSilentSwitch: PropTypes.oneOf(['ignore', 'obey']),
@ -446,8 +439,8 @@ Video.propTypes = {
onPlaybackRateChange: PropTypes.func,
onAudioFocusChanged: PropTypes.func,
onAudioBecomingNoisy: PropTypes.func,
onIsPictureInPictureSupported: PropTypes.func,
onIsPictureInPictureActive: PropTypes.func,
onPictureInPictureStatusChanged: PropTypes.func,
needsToRestoreUserInterfaceForPictureInPictureStop: PropTypes.func,
onExternalPlaybackChange: PropTypes.func,
/* Required by react-native */

View File

@ -38,8 +38,8 @@
@property (nonatomic, copy) RCTBubblingEventBlock onPlaybackResume;
@property (nonatomic, copy) RCTBubblingEventBlock onPlaybackRateChange;
@property (nonatomic, copy) RCTBubblingEventBlock onVideoExternalPlaybackChange;
@property (nonatomic, copy) RCTBubblingEventBlock onIsPictureInPictureSupported;
@property (nonatomic, copy) RCTBubblingEventBlock onIsPictureInPictureActive;
@property (nonatomic, copy) RCTBubblingEventBlock onPictureInPictureStatusChanged;
@property (nonatomic, copy) RCTBubblingEventBlock onRestoreUserInterfaceForPictureInPictureStop;
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;

View File

@ -66,6 +66,7 @@ static int const RCTVideoUnset = -1;
BOOL _playbackStalled;
BOOL _playInBackground;
BOOL _playWhenInactive;
BOOL _pictureInPicture;
NSString * _ignoreSilentSwitch;
NSString * _resizeMode;
BOOL _fullscreen;
@ -102,6 +103,7 @@ static int const RCTVideoUnset = -1;
_playInBackground = false;
_allowsExternalPlayback = YES;
_playWhenInactive = false;
_pictureInPicture = false;
_ignoreSilentSwitch = @"inherit"; // inherit, ignore, obey
_restoreUserInterfaceForPIPStopCompletionHandler = NULL;
#if __has_include(<react-native-video/RCTVideoCache.h>)
@ -382,12 +384,6 @@ static int const RCTVideoUnset = -1;
@"target": self.reactTag
});
}
if (@available(iOS 9, *)) {
if (self.onIsPictureInPictureSupported) {
self.onIsPictureInPictureSupported(@{@"supported": [NSNumber numberWithBool:(bool)[AVPictureInPictureController isPictureInPictureSupported]]});
}
}
}];
});
_videoLoadStarted = YES;
@ -791,11 +787,16 @@ static int const RCTVideoUnset = -1;
- (void)setPictureInPicture:(BOOL)pictureInPicture
{
if (_pipController && pictureInPicture && ![_pipController isPictureInPictureActive]) {
if (_pictureInPicture == pictureInPicture) {
return;
}
_pictureInPicture = pictureInPicture;
if (_pipController && _pictureInPicture && ![_pipController isPictureInPictureActive]) {
dispatch_async(dispatch_get_main_queue(), ^{
[_pipController startPictureInPicture];
});
} else if (_pipController && !pictureInPicture && [_pipController isPictureInPictureActive]) {
} else if (_pipController && !_pictureInPicture && [_pipController isPictureInPictureActive]) {
dispatch_async(dispatch_get_main_queue(), ^{
[_pipController stopPictureInPicture];
});
@ -811,12 +812,10 @@ static int const RCTVideoUnset = -1;
}
- (void)setupPipController {
if (@available(iOS 9, *)) {
if (!_pipController && _playerLayer && [AVPictureInPictureController isPictureInPictureSupported]) {
// Create new controller passing reference to the AVPlayerLayer
_pipController = [[AVPictureInPictureController alloc] initWithPlayerLayer:_playerLayer];
_pipController.delegate = self;
}
if (!_pipController && _playerLayer && [AVPictureInPictureController isPictureInPictureSupported]) {
// Create new controller passing reference to the AVPlayerLayer
_pipController = [[AVPictureInPictureController alloc] initWithPlayerLayer:_playerLayer];
_pipController.delegate = self;
}
}
@ -1535,14 +1534,18 @@ static int const RCTVideoUnset = -1;
#pragma mark - Picture in Picture
- (void)pictureInPictureControllerDidStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
if (self.onIsPictureInPictureActive && _pipController) {
self.onIsPictureInPictureActive(@{@"active": [NSNumber numberWithBool:false]});
if (self.onPictureInPictureStatusChanged) {
self.onPictureInPictureStatusChanged(@{
@"isActive": [NSNumber numberWithBool:false]
});
}
}
- (void)pictureInPictureControllerDidStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
if (self.onIsPictureInPictureActive && _pipController) {
self.onIsPictureInPictureActive(@{@"active": [NSNumber numberWithBool:true]});
if (self.onPictureInPictureStatusChanged) {
self.onPictureInPictureStatusChanged(@{
@"isActive": [NSNumber numberWithBool:true]
});
}
}
@ -1560,6 +1563,9 @@ static int const RCTVideoUnset = -1;
- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL))completionHandler {
NSAssert(_restoreUserInterfaceForPIPStopCompletionHandler == NULL, @"restoreUserInterfaceForPIPStopCompletionHandler was not called after picture in picture was exited.");
if (self.onRestoreUserInterfaceForPictureInPictureStop) {
self.onRestoreUserInterfaceForPictureInPictureStop(@{});
}
_restoreUserInterfaceForPIPStopCompletionHandler = completionHandler;
}

View File

@ -32,6 +32,7 @@ RCT_EXPORT_VIEW_PROPERTY(controls, BOOL);
RCT_EXPORT_VIEW_PROPERTY(volume, float);
RCT_EXPORT_VIEW_PROPERTY(playInBackground, BOOL);
RCT_EXPORT_VIEW_PROPERTY(playWhenInactive, BOOL);
RCT_EXPORT_VIEW_PROPERTY(pictureInPicture, BOOL);
RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString);
RCT_EXPORT_VIEW_PROPERTY(rate, float);
RCT_EXPORT_VIEW_PROPERTY(seek, NSDictionary);
@ -42,7 +43,6 @@ RCT_EXPORT_VIEW_PROPERTY(fullscreenOrientation, NSString);
RCT_EXPORT_VIEW_PROPERTY(filter, NSString);
RCT_EXPORT_VIEW_PROPERTY(filterEnabled, BOOL);
RCT_EXPORT_VIEW_PROPERTY(progressUpdateInterval, float);
RCT_EXPORT_VIEW_PROPERTY(pictureInPicture, BOOL);
RCT_EXPORT_VIEW_PROPERTY(restoreUserInterfaceForPIPStopCompletionHandler, BOOL);
/* Should support: onLoadStart, onLoad, and onError to stay consistent with Image */
RCT_EXPORT_VIEW_PROPERTY(onVideoLoadStart, RCTBubblingEventBlock);
@ -79,8 +79,8 @@ RCT_REMAP_METHOD(save,
}
}];
}
RCT_EXPORT_VIEW_PROPERTY(onIsPictureInPictureSupported, RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onIsPictureInPictureActive, RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onPictureInPictureStatusChanged, RCTBubblingEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onRestoreUserInterfaceForPictureInPictureStop, RCTBubblingEventBlock);
- (NSDictionary *)constantsToExport
{